| /* |
| * 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. |
| */ |
| |
| /** |
| * \file ast_to_hir.c |
| * Convert abstract syntax to to high-level intermediate reprensentation (HIR). |
| * |
| * During the conversion to HIR, the majority of the symantic checking is |
| * preformed on the program. This includes: |
| * |
| * * Symbol table management |
| * * Type checking |
| * * Function binding |
| * |
| * The majority of this work could be done during parsing, and the parser could |
| * probably generate HIR directly. However, this results in frequent changes |
| * to the parser code. Since we do not assume that every system this complier |
| * is built on will have Flex and Bison installed, we have to store the code |
| * generated by these tools in our version control system. In other parts of |
| * the system we've seen problems where a parser was changed but the generated |
| * code was not committed, merge conflicts where created because two developers |
| * had slightly different versions of Bison installed, etc. |
| * |
| * I have also noticed that running Bison generated parsers in GDB is very |
| * irritating. When you get a segfault on '$$ = $1->foo', you can't very |
| * well 'print $1' in GDB. |
| * |
| * As a result, my preference is to put as little C code as possible in the |
| * parser (and lexer) sources. |
| */ |
| |
| #include "glsl_symbol_table.h" |
| #include "glsl_parser_extras.h" |
| #include "ast.h" |
| #include "glsl_types.h" |
| #include "program/hash_table.h" |
| #include "main/shaderobj.h" |
| #include "ir.h" |
| #include "ir_builder.h" |
| |
| using namespace ir_builder; |
| |
| static void |
| detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, |
| exec_list *instructions); |
| static void |
| remove_per_vertex_blocks(exec_list *instructions, |
| _mesa_glsl_parse_state *state, ir_variable_mode mode); |
| |
| /** |
| * Visitor class that finds the first instance of any write-only variable that |
| * is ever read, if any |
| */ |
| class read_from_write_only_variable_visitor : public ir_hierarchical_visitor |
| { |
| public: |
| read_from_write_only_variable_visitor() : found(NULL) |
| { |
| } |
| |
| virtual ir_visitor_status visit(ir_dereference_variable *ir) |
| { |
| if (this->in_assignee) |
| return visit_continue; |
| |
| ir_variable *var = ir->variable_referenced(); |
| /* We can have image_write_only set on both images and buffer variables, |
| * but in the former there is a distinction between reads from |
| * the variable itself (write_only) and from the memory they point to |
| * (image_write_only), while in the case of buffer variables there is |
| * no such distinction, that is why this check here is limited to |
| * buffer variables alone. |
| */ |
| if (!var || var->data.mode != ir_var_shader_storage) |
| return visit_continue; |
| |
| if (var->data.image_write_only) { |
| found = var; |
| return visit_stop; |
| } |
| |
| return visit_continue; |
| } |
| |
| ir_variable *get_variable() { |
| return found; |
| } |
| |
| private: |
| ir_variable *found; |
| }; |
| |
| void |
| _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) |
| { |
| _mesa_glsl_initialize_variables(instructions, state); |
| |
| state->symbols->separate_function_namespace = state->language_version == 110; |
| |
| state->current_function = NULL; |
| |
| state->toplevel_ir = instructions; |
| |
| state->gs_input_prim_type_specified = false; |
| state->tcs_output_vertices_specified = false; |
| state->cs_input_local_size_specified = false; |
| |
| /* Section 4.2 of the GLSL 1.20 specification states: |
| * "The built-in functions are scoped in a scope outside the global scope |
| * users declare global variables in. That is, a shader's global scope, |
| * available for user-defined functions and global variables, is nested |
| * inside the scope containing the built-in functions." |
| * |
| * Since built-in functions like ftransform() access built-in variables, |
| * it follows that those must be in the outer scope as well. |
| * |
| * We push scope here to create this nesting effect...but don't pop. |
| * This way, a shader's globals are still in the symbol table for use |
| * by the linker. |
| */ |
| state->symbols->push_scope(); |
| |
| foreach_list_typed (ast_node, ast, link, & state->translation_unit) |
| ast->hir(instructions, state); |
| |
| detect_recursion_unlinked(state, instructions); |
| detect_conflicting_assignments(state, instructions); |
| |
| state->toplevel_ir = NULL; |
| |
| /* Move all of the variable declarations to the front of the IR list, and |
| * reverse the order. This has the (intended!) side effect that vertex |
| * shader inputs and fragment shader outputs will appear in the IR in the |
| * same order that they appeared in the shader code. This results in the |
| * locations being assigned in the declared order. Many (arguably buggy) |
| * applications depend on this behavior, and it matches what nearly all |
| * other drivers do. |
| */ |
| foreach_in_list_safe(ir_instruction, node, instructions) { |
| ir_variable *const var = node->as_variable(); |
| |
| if (var == NULL) |
| continue; |
| |
| var->remove(); |
| instructions->push_head(var); |
| } |
| |
| /* Figure out if gl_FragCoord is actually used in fragment shader */ |
| ir_variable *const var = state->symbols->get_variable("gl_FragCoord"); |
| if (var != NULL) |
| state->fs_uses_gl_fragcoord = var->data.used; |
| |
| /* From section 7.1 (Built-In Language Variables) of the GLSL 4.10 spec: |
| * |
| * If multiple shaders using members of a built-in block belonging to |
| * the same interface are linked together in the same program, they |
| * must all redeclare the built-in block in the same way, as described |
| * in section 4.3.7 "Interface Blocks" for interface block matching, or |
| * a link error will result. |
| * |
| * The phrase "using members of a built-in block" implies that if two |
| * shaders are linked together and one of them *does not use* any members |
| * of the built-in block, then that shader does not need to have a matching |
| * redeclaration of the built-in block. |
| * |
| * This appears to be a clarification to the behaviour established for |
| * gl_PerVertex by GLSL 1.50, therefore implement it regardless of GLSL |
| * version. |
| * |
| * The definition of "interface" in section 4.3.7 that applies here is as |
| * follows: |
| * |
| * The boundary between adjacent programmable pipeline stages: This |
| * spans all the outputs in all compilation units of the first stage |
| * and all the inputs in all compilation units of the second stage. |
| * |
| * Therefore this rule applies to both inter- and intra-stage linking. |
| * |
| * The easiest way to implement this is to check whether the shader uses |
| * gl_PerVertex right after ast-to-ir conversion, and if it doesn't, simply |
| * remove all the relevant variable declaration from the IR, so that the |
| * linker won't see them and complain about mismatches. |
| */ |
| remove_per_vertex_blocks(instructions, state, ir_var_shader_in); |
| remove_per_vertex_blocks(instructions, state, ir_var_shader_out); |
| |
| /* Check that we don't have reads from write-only variables */ |
| read_from_write_only_variable_visitor v; |
| v.run(instructions); |
| ir_variable *error_var = v.get_variable(); |
| if (error_var) { |
| /* It would be nice to have proper location information, but for that |
| * we would need to check this as we process each kind of AST node |
| */ |
| YYLTYPE loc; |
| memset(&loc, 0, sizeof(loc)); |
| _mesa_glsl_error(&loc, state, "Read from write-only variable `%s'", |
| error_var->name); |
| } |
| } |
| |
| |
| static ir_expression_operation |
| get_conversion_operation(const glsl_type *to, const glsl_type *from, |
| struct _mesa_glsl_parse_state *state) |
| { |
| switch (to->base_type) { |
| case GLSL_TYPE_FLOAT: |
| switch (from->base_type) { |
| case GLSL_TYPE_INT: return ir_unop_i2f; |
| case GLSL_TYPE_UINT: return ir_unop_u2f; |
| case GLSL_TYPE_DOUBLE: return ir_unop_d2f; |
| default: return (ir_expression_operation)0; |
| } |
| |
| case GLSL_TYPE_UINT: |
| if (!state->is_version(400, 0) && !state->ARB_gpu_shader5_enable) |
| return (ir_expression_operation)0; |
| switch (from->base_type) { |
| case GLSL_TYPE_INT: return ir_unop_i2u; |
| default: return (ir_expression_operation)0; |
| } |
| |
| case GLSL_TYPE_DOUBLE: |
| if (!state->has_double()) |
| return (ir_expression_operation)0; |
| switch (from->base_type) { |
| case GLSL_TYPE_INT: return ir_unop_i2d; |
| case GLSL_TYPE_UINT: return ir_unop_u2d; |
| case GLSL_TYPE_FLOAT: return ir_unop_f2d; |
| default: return (ir_expression_operation)0; |
| } |
| |
| default: return (ir_expression_operation)0; |
| } |
| } |
| |
| |
| /** |
| * If a conversion is available, convert one operand to a different type |
| * |
| * The \c from \c ir_rvalue is converted "in place". |
| * |
| * \param to Type that the operand it to be converted to |
| * \param from Operand that is being converted |
| * \param state GLSL compiler state |
| * |
| * \return |
| * If a conversion is possible (or unnecessary), \c true is returned. |
| * Otherwise \c false is returned. |
| */ |
| bool |
| apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from, |
| struct _mesa_glsl_parse_state *state) |
| { |
| void *ctx = state; |
| if (to->base_type == from->type->base_type) |
| return true; |
| |
| /* Prior to GLSL 1.20, there are no implicit conversions */ |
| if (!state->is_version(120, 0)) |
| return false; |
| |
| /* From page 27 (page 33 of the PDF) of the GLSL 1.50 spec: |
| * |
| * "There are no implicit array or structure conversions. For |
| * example, an array of int cannot be implicitly converted to an |
| * array of float. |
| */ |
| if (!to->is_numeric() || !from->type->is_numeric()) |
| return false; |
| |
| /* We don't actually want the specific type `to`, we want a type |
| * with the same base type as `to`, but the same vector width as |
| * `from`. |
| */ |
| to = glsl_type::get_instance(to->base_type, from->type->vector_elements, |
| from->type->matrix_columns); |
| |
| ir_expression_operation op = get_conversion_operation(to, from->type, state); |
| if (op) { |
| from = new(ctx) ir_expression(op, to, from, NULL); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| |
| static const struct glsl_type * |
| arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, |
| bool multiply, |
| struct _mesa_glsl_parse_state *state, YYLTYPE *loc) |
| { |
| const glsl_type *type_a = value_a->type; |
| const glsl_type *type_b = value_b->type; |
| |
| /* From GLSL 1.50 spec, page 56: |
| * |
| * "The arithmetic binary operators add (+), subtract (-), |
| * multiply (*), and divide (/) operate on integer and |
| * floating-point scalars, vectors, and matrices." |
| */ |
| if (!type_a->is_numeric() || !type_b->is_numeric()) { |
| _mesa_glsl_error(loc, state, |
| "operands to arithmetic operators must be numeric"); |
| return glsl_type::error_type; |
| } |
| |
| |
| /* "If one operand is floating-point based and the other is |
| * not, then the conversions from Section 4.1.10 "Implicit |
| * Conversions" are applied to the non-floating-point-based operand." |
| */ |
| if (!apply_implicit_conversion(type_a, value_b, state) |
| && !apply_implicit_conversion(type_b, value_a, state)) { |
| _mesa_glsl_error(loc, state, |
| "could not implicitly convert operands to " |
| "arithmetic operator"); |
| return glsl_type::error_type; |
| } |
| type_a = value_a->type; |
| type_b = value_b->type; |
| |
| /* "If the operands are integer types, they must both be signed or |
| * both be unsigned." |
| * |
| * From this rule and the preceeding conversion it can be inferred that |
| * both types must be GLSL_TYPE_FLOAT, or GLSL_TYPE_UINT, or GLSL_TYPE_INT. |
| * The is_numeric check above already filtered out the case where either |
| * type is not one of these, so now the base types need only be tested for |
| * equality. |
| */ |
| if (type_a->base_type != type_b->base_type) { |
| _mesa_glsl_error(loc, state, |
| "base type mismatch for arithmetic operator"); |
| return glsl_type::error_type; |
| } |
| |
| /* "All arithmetic binary operators result in the same fundamental type |
| * (signed integer, unsigned integer, or floating-point) as the |
| * operands they operate on, after operand type conversion. After |
| * conversion, the following cases are valid |
| * |
| * * The two operands are scalars. In this case the operation is |
| * applied, resulting in a scalar." |
| */ |
| if (type_a->is_scalar() && type_b->is_scalar()) |
| return type_a; |
| |
| /* "* One operand is a scalar, and the other is a vector or matrix. |
| * In this case, the scalar operation is applied independently to each |
| * component of the vector or matrix, resulting in the same size |
| * vector or matrix." |
| */ |
| if (type_a->is_scalar()) { |
| if (!type_b->is_scalar()) |
| return type_b; |
| } else if (type_b->is_scalar()) { |
| return type_a; |
| } |
| |
| /* All of the combinations of <scalar, scalar>, <vector, scalar>, |
| * <scalar, vector>, <scalar, matrix>, and <matrix, scalar> have been |
| * handled. |
| */ |
| assert(!type_a->is_scalar()); |
| assert(!type_b->is_scalar()); |
| |
| /* "* The two operands are vectors of the same size. In this case, the |
| * operation is done component-wise resulting in the same size |
| * vector." |
| */ |
| if (type_a->is_vector() && type_b->is_vector()) { |
| if (type_a == type_b) { |
| return type_a; |
| } else { |
| _mesa_glsl_error(loc, state, |
| "vector size mismatch for arithmetic operator"); |
| return glsl_type::error_type; |
| } |
| } |
| |
| /* All of the combinations of <scalar, scalar>, <vector, scalar>, |
| * <scalar, vector>, <scalar, matrix>, <matrix, scalar>, and |
| * <vector, vector> have been handled. At least one of the operands must |
| * be matrix. Further, since there are no integer matrix types, the base |
| * type of both operands must be float. |
| */ |
| assert(type_a->is_matrix() || type_b->is_matrix()); |
| assert(type_a->base_type == GLSL_TYPE_FLOAT || |
| type_a->base_type == GLSL_TYPE_DOUBLE); |
| assert(type_b->base_type == GLSL_TYPE_FLOAT || |
| type_b->base_type == GLSL_TYPE_DOUBLE); |
| |
| /* "* The operator is add (+), subtract (-), or divide (/), and the |
| * operands are matrices with the same number of rows and the same |
| * number of columns. In this case, the operation is done component- |
| * wise resulting in the same size matrix." |
| * * The operator is multiply (*), where both operands are matrices or |
| * one operand is a vector and the other a matrix. A right vector |
| * operand is treated as a column vector and a left vector operand as a |
| * row vector. In all these cases, it is required that the number of |
| * columns of the left operand is equal to the number of rows of the |
| * right operand. Then, the multiply (*) operation does a linear |
| * algebraic multiply, yielding an object that has the same number of |
| * rows as the left operand and the same number of columns as the right |
| * operand. Section 5.10 "Vector and Matrix Operations" explains in |
| * more detail how vectors and matrices are operated on." |
| */ |
| if (! multiply) { |
| if (type_a == type_b) |
| return type_a; |
| } else { |
| const glsl_type *type = glsl_type::get_mul_type(type_a, type_b); |
| |
| if (type == glsl_type::error_type) { |
| _mesa_glsl_error(loc, state, |
| "size mismatch for matrix multiplication"); |
| } |
| |
| return type; |
| } |
| |
| |
| /* "All other cases are illegal." |
| */ |
| _mesa_glsl_error(loc, state, "type mismatch"); |
| return glsl_type::error_type; |
| } |
| |
| |
| static const struct glsl_type * |
| unary_arithmetic_result_type(const struct glsl_type *type, |
| struct _mesa_glsl_parse_state *state, YYLTYPE *loc) |
| { |
| /* From GLSL 1.50 spec, page 57: |
| * |
| * "The arithmetic unary operators negate (-), post- and pre-increment |
| * and decrement (-- and ++) operate on integer or floating-point |
| * values (including vectors and matrices). All unary operators work |
| * component-wise on their operands. These result with the same type |
| * they operated on." |
| */ |
| if (!type->is_numeric()) { |
| _mesa_glsl_error(loc, state, |
| "operands to arithmetic operators must be numeric"); |
| return glsl_type::error_type; |
| } |
| |
| return type; |
| } |
| |
| /** |
| * \brief Return the result type of a bit-logic operation. |
| * |
| * If the given types to the bit-logic operator are invalid, return |
| * glsl_type::error_type. |
| * |
| * \param type_a Type of LHS of bit-logic op |
| * \param type_b Type of RHS of bit-logic op |
| */ |
| static const struct glsl_type * |
| bit_logic_result_type(const struct glsl_type *type_a, |
| const struct glsl_type *type_b, |
| ast_operators op, |
| struct _mesa_glsl_parse_state *state, YYLTYPE *loc) |
| { |
| if (!state->check_bitwise_operations_allowed(loc)) { |
| return glsl_type::error_type; |
| } |
| |
| /* From page 50 (page 56 of PDF) of GLSL 1.30 spec: |
| * |
| * "The bitwise operators and (&), exclusive-or (^), and inclusive-or |
| * (|). The operands must be of type signed or unsigned integers or |
| * integer vectors." |
| */ |
| if (!type_a->is_integer()) { |
| _mesa_glsl_error(loc, state, "LHS of `%s' must be an integer", |
| ast_expression::operator_string(op)); |
| return glsl_type::error_type; |
| } |
| if (!type_b->is_integer()) { |
| _mesa_glsl_error(loc, state, "RHS of `%s' must be an integer", |
| ast_expression::operator_string(op)); |
| return glsl_type::error_type; |
| } |
| |
| /* "The fundamental types of the operands (signed or unsigned) must |
| * match," |
| */ |
| if (type_a->base_type != type_b->base_type) { |
| _mesa_glsl_error(loc, state, "operands of `%s' must have the same " |
| "base type", ast_expression::operator_string(op)); |
| return glsl_type::error_type; |
| } |
| |
| /* "The operands cannot be vectors of differing size." */ |
| if (type_a->is_vector() && |
| type_b->is_vector() && |
| type_a->vector_elements != type_b->vector_elements) { |
| _mesa_glsl_error(loc, state, "operands of `%s' cannot be vectors of " |
| "different sizes", ast_expression::operator_string(op)); |
| return glsl_type::error_type; |
| } |
| |
| /* "If one operand is a scalar and the other a vector, the scalar is |
| * applied component-wise to the vector, resulting in the same type as |
| * the vector. The fundamental types of the operands [...] will be the |
| * resulting fundamental type." |
| */ |
| if (type_a->is_scalar()) |
| return type_b; |
| else |
| return type_a; |
| } |
| |
| static const struct glsl_type * |
| modulus_result_type(const struct glsl_type *type_a, |
| const struct glsl_type *type_b, |
| struct _mesa_glsl_parse_state *state, YYLTYPE *loc) |
| { |
| if (!state->check_version(130, 300, loc, "operator '%%' is reserved")) { |
| return glsl_type::error_type; |
| } |
| |
| /* From GLSL 1.50 spec, page 56: |
| * "The operator modulus (%) operates on signed or unsigned integers or |
| * integer vectors. The operand types must both be signed or both be |
| * unsigned." |
| */ |
| if (!type_a->is_integer()) { |
| _mesa_glsl_error(loc, state, "LHS of operator %% must be an integer"); |
| return glsl_type::error_type; |
| } |
| if (!type_b->is_integer()) { |
| _mesa_glsl_error(loc, state, "RHS of operator %% must be an integer"); |
| return glsl_type::error_type; |
| } |
| if (type_a->base_type != type_b->base_type) { |
| _mesa_glsl_error(loc, state, |
| "operands of %% must have the same base type"); |
| return glsl_type::error_type; |
| } |
| |
| /* "The operands cannot be vectors of differing size. If one operand is |
| * a scalar and the other vector, then the scalar is applied component- |
| * wise to the vector, resulting in the same type as the vector. If both |
| * are vectors of the same size, the result is computed component-wise." |
| */ |
| if (type_a->is_vector()) { |
| if (!type_b->is_vector() |
| || (type_a->vector_elements == type_b->vector_elements)) |
| return type_a; |
| } else |
| return type_b; |
| |
| /* "The operator modulus (%) is not defined for any other data types |
| * (non-integer types)." |
| */ |
| _mesa_glsl_error(loc, state, "type mismatch"); |
| return glsl_type::error_type; |
| } |
| |
| |
| static const struct glsl_type * |
| relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, |
| struct _mesa_glsl_parse_state *state, YYLTYPE *loc) |
| { |
| const glsl_type *type_a = value_a->type; |
| const glsl_type *type_b = value_b->type; |
| |
| /* From GLSL 1.50 spec, page 56: |
| * "The relational operators greater than (>), less than (<), greater |
| * than or equal (>=), and less than or equal (<=) operate only on |
| * scalar integer and scalar floating-point expressions." |
| */ |
| if (!type_a->is_numeric() |
| || !type_b->is_numeric() |
| || !type_a->is_scalar() |
| || !type_b->is_scalar()) { |
| _mesa_glsl_error(loc, state, |
| "operands to relational operators must be scalar and " |
| "numeric"); |
| return glsl_type::error_type; |
| } |
| |
| /* "Either the operands' types must match, or the conversions from |
| * Section 4.1.10 "Implicit Conversions" will be applied to the integer |
| * operand, after which the types must match." |
| */ |
| if (!apply_implicit_conversion(type_a, value_b, state) |
| && !apply_implicit_conversion(type_b, value_a, state)) { |
| _mesa_glsl_error(loc, state, |
| "could not implicitly convert operands to " |
| "relational operator"); |
| return glsl_type::error_type; |
| } |
| type_a = value_a->type; |
| type_b = value_b->type; |
| |
| if (type_a->base_type != type_b->base_type) { |
| _mesa_glsl_error(loc, state, "base type mismatch"); |
| return glsl_type::error_type; |
| } |
| |
| /* "The result is scalar Boolean." |
| */ |
| return glsl_type::bool_type; |
| } |
| |
| /** |
| * \brief Return the result type of a bit-shift operation. |
| * |
| * If the given types to the bit-shift operator are invalid, return |
| * glsl_type::error_type. |
| * |
| * \param type_a Type of LHS of bit-shift op |
| * \param type_b Type of RHS of bit-shift op |
| */ |
| static const struct glsl_type * |
| shift_result_type(const struct glsl_type *type_a, |
| const struct glsl_type *type_b, |
| ast_operators op, |
| struct _mesa_glsl_parse_state *state, YYLTYPE *loc) |
| { |
| if (!state->check_bitwise_operations_allowed(loc)) { |
| return glsl_type::error_type; |
| } |
| |
| /* From page 50 (page 56 of the PDF) of the GLSL 1.30 spec: |
| * |
| * "The shift operators (<<) and (>>). For both operators, the operands |
| * must be signed or unsigned integers or integer vectors. One operand |
| * can be signed while the other is unsigned." |
| */ |
| if (!type_a->is_integer()) { |
| _mesa_glsl_error(loc, state, "LHS of operator %s must be an integer or " |
| "integer vector", ast_expression::operator_string(op)); |
| return glsl_type::error_type; |
| |
| } |
| if (!type_b->is_integer()) { |
| _mesa_glsl_error(loc, state, "RHS of operator %s must be an integer or " |
| "integer vector", ast_expression::operator_string(op)); |
| return glsl_type::error_type; |
| } |
| |
| /* "If the first operand is a scalar, the second operand has to be |
| * a scalar as well." |
| */ |
| if (type_a->is_scalar() && !type_b->is_scalar()) { |
| _mesa_glsl_error(loc, state, "if the first operand of %s is scalar, the " |
| "second must be scalar as well", |
| ast_expression::operator_string(op)); |
| return glsl_type::error_type; |
| } |
| |
| /* If both operands are vectors, check that they have same number of |
| * elements. |
| */ |
| if (type_a->is_vector() && |
| type_b->is_vector() && |
| type_a->vector_elements != type_b->vector_elements) { |
| _mesa_glsl_error(loc, state, "vector operands to operator %s must " |
| "have same number of elements", |
| ast_expression::operator_string(op)); |
| return glsl_type::error_type; |
| } |
| |
| /* "In all cases, the resulting type will be the same type as the left |
| * operand." |
| */ |
| return type_a; |
| } |
| |
| /** |
| * Returns the innermost array index expression in an rvalue tree. |
| * This is the largest indexing level -- if an array of blocks, then |
| * it is the block index rather than an indexing expression for an |
| * array-typed member of an array of blocks. |
| */ |
| static ir_rvalue * |
| find_innermost_array_index(ir_rvalue *rv) |
| { |
| ir_dereference_array *last = NULL; |
| while (rv) { |
| if (rv->as_dereference_array()) { |
| last = rv->as_dereference_array(); |
| rv = last->array; |
| } else if (rv->as_dereference_record()) |
| rv = rv->as_dereference_record()->record; |
| else if (rv->as_swizzle()) |
| rv = rv->as_swizzle()->val; |
| else |
| rv = NULL; |
| } |
| |
| if (last) |
| return last->array_index; |
| |
| return NULL; |
| } |
| |
| /** |
| * Validates that a value can be assigned to a location with a specified type |
| * |
| * Validates that \c rhs can be assigned to some location. If the types are |
| * not an exact match but an automatic conversion is possible, \c rhs will be |
| * converted. |
| * |
| * \return |
| * \c NULL if \c rhs cannot be assigned to a location with type \c lhs_type. |
| * Otherwise the actual RHS to be assigned will be returned. This may be |
| * \c rhs, or it may be \c rhs after some type conversion. |
| * |
| * \note |
| * In addition to being used for assignments, this function is used to |
| * type-check return values. |
| */ |
| static ir_rvalue * |
| validate_assignment(struct _mesa_glsl_parse_state *state, |
| YYLTYPE loc, ir_rvalue *lhs, |
| ir_rvalue *rhs, bool is_initializer) |
| { |
| /* If there is already some error in the RHS, just return it. Anything |
| * else will lead to an avalanche of error message back to the user. |
| */ |
| if (rhs->type->is_error()) |
| return rhs; |
| |
| /* In the Tessellation Control Shader: |
| * If a per-vertex output variable is used as an l-value, it is an error |
| * if the expression indicating the vertex number is not the identifier |
| * `gl_InvocationID`. |
| */ |
| if (state->stage == MESA_SHADER_TESS_CTRL) { |
| ir_variable *var = lhs->variable_referenced(); |
| if (var->data.mode == ir_var_shader_out && !var->data.patch) { |
| ir_rvalue *index = find_innermost_array_index(lhs); |
| ir_variable *index_var = index ? index->variable_referenced() : NULL; |
| if (!index_var || strcmp(index_var->name, "gl_InvocationID") != 0) { |
| _mesa_glsl_error(&loc, state, |
| "Tessellation control shader outputs can only " |
| "be indexed by gl_InvocationID"); |
| return NULL; |
| } |
| } |
| } |
| |
| /* If the types are identical, the assignment can trivially proceed. |
| */ |
| if (rhs->type == lhs->type) |
| return rhs; |
| |
| /* If the array element types are the same and the LHS is unsized, |
| * the assignment is okay for initializers embedded in variable |
| * declarations. |
| * |
| * Note: Whole-array assignments are not permitted in GLSL 1.10, but this |
| * is handled by ir_dereference::is_lvalue. |
| */ |
| if (lhs->type->is_unsized_array() && rhs->type->is_array() |
| && (lhs->type->fields.array == rhs->type->fields.array)) { |
| if (is_initializer) { |
| return rhs; |
| } else { |
| _mesa_glsl_error(&loc, state, |
| "implicitly sized arrays cannot be assigned"); |
| return NULL; |
| } |
| } |
| |
| /* Check for implicit conversion in GLSL 1.20 */ |
| if (apply_implicit_conversion(lhs->type, rhs, state)) { |
| if (rhs->type == lhs->type) |
| return rhs; |
| } |
| |
| _mesa_glsl_error(&loc, state, |
| "%s of type %s cannot be assigned to " |
| "variable of type %s", |
| is_initializer ? "initializer" : "value", |
| rhs->type->name, lhs->type->name); |
| |
| return NULL; |
| } |
| |
| static void |
| mark_whole_array_access(ir_rvalue *access) |
| { |
| ir_dereference_variable *deref = access->as_dereference_variable(); |
| |
| if (deref && deref->var) { |
| deref->var->data.max_array_access = deref->type->length - 1; |
| } |
| } |
| |
| static bool |
| do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, |
| const char *non_lvalue_description, |
| ir_rvalue *lhs, ir_rvalue *rhs, |
| ir_rvalue **out_rvalue, bool needs_rvalue, |
| bool is_initializer, |
| YYLTYPE lhs_loc) |
| { |
| void *ctx = state; |
| bool error_emitted = (lhs->type->is_error() || rhs->type->is_error()); |
| ir_rvalue *extract_channel = NULL; |
| |
| /* If the assignment LHS comes back as an ir_binop_vector_extract |
| * expression, move it to the RHS as an ir_triop_vector_insert. |
| */ |
| if (lhs->ir_type == ir_type_expression) { |
| ir_expression *const lhs_expr = lhs->as_expression(); |
| |
| if (unlikely(lhs_expr->operation == ir_binop_vector_extract)) { |
| ir_rvalue *new_rhs = |
| validate_assignment(state, lhs_loc, lhs, |
| rhs, is_initializer); |
| |
| if (new_rhs == NULL) { |
| return lhs; |
| } else { |
| /* This converts: |
| * - LHS: (expression float vector_extract <vec> <channel>) |
| * - RHS: <scalar> |
| * into: |
| * - LHS: <vec> |
| * - RHS: (expression vec2 vector_insert <vec> <channel> <scalar>) |
| * |
| * The LHS type is now a vector instead of a scalar. Since GLSL |
| * allows assignments to be used as rvalues, we need to re-extract |
| * the channel from assignment_temp when returning the rvalue. |
| */ |
| extract_channel = lhs_expr->operands[1]; |
| rhs = new(ctx) ir_expression(ir_triop_vector_insert, |
| lhs_expr->operands[0]->type, |
| lhs_expr->operands[0], |
| new_rhs, |
| extract_channel); |
| lhs = lhs_expr->operands[0]->clone(ctx, NULL); |
| } |
| } |
| } |
| |
| ir_variable *lhs_var = lhs->variable_referenced(); |
| if (lhs_var) |
| lhs_var->data.assigned = true; |
| |
| if (!error_emitted) { |
| if (non_lvalue_description != NULL) { |
| _mesa_glsl_error(&lhs_loc, state, |
| "assignment to %s", |
| non_lvalue_description); |
| error_emitted = true; |
| } else if (lhs_var != NULL && (lhs_var->data.read_only || |
| (lhs_var->data.mode == ir_var_shader_storage && |
| lhs_var->data.image_read_only))) { |
| /* We can have image_read_only set on both images and buffer variables, |
| * but in the former there is a distinction between assignments to |
| * the variable itself (read_only) and to the memory they point to |
| * (image_read_only), while in the case of buffer variables there is |
| * no such distinction, that is why this check here is limited to |
| * buffer variables alone. |
| */ |
| _mesa_glsl_error(&lhs_loc, state, |
| "assignment to read-only variable '%s'", |
| lhs_var->name); |
| error_emitted = true; |
| } else if (lhs->type->is_array() && |
| !state->check_version(120, 300, &lhs_loc, |
| "whole array assignment forbidden")) { |
| /* From page 32 (page 38 of the PDF) of the GLSL 1.10 spec: |
| * |
| * "Other binary or unary expressions, non-dereferenced |
| * arrays, function names, swizzles with repeated fields, |
| * and constants cannot be l-values." |
| * |
| * The restriction on arrays is lifted in GLSL 1.20 and GLSL ES 3.00. |
| */ |
| error_emitted = true; |
| } else if (!lhs->is_lvalue()) { |
| _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment"); |
| error_emitted = true; |
| } |
| } |
| |
| ir_rvalue *new_rhs = |
| validate_assignment(state, lhs_loc, lhs, rhs, is_initializer); |
| if (new_rhs != NULL) { |
| rhs = new_rhs; |
| |
| /* If the LHS array was not declared with a size, it takes it size from |
| * the RHS. If the LHS is an l-value and a whole array, it must be a |
| * dereference of a variable. Any other case would require that the LHS |
| * is either not an l-value or not a whole array. |
| */ |
| if (lhs->type->is_unsized_array()) { |
| ir_dereference *const d = lhs->as_dereference(); |
| |
| assert(d != NULL); |
| |
| ir_variable *const var = d->variable_referenced(); |
| |
| assert(var != NULL); |
| |
| if (var->data.max_array_access >= unsigned(rhs->type->array_size())) { |
| /* FINISHME: This should actually log the location of the RHS. */ |
| _mesa_glsl_error(& lhs_loc, state, "array size must be > %u due to " |
| "previous access", |
| var->data.max_array_access); |
| } |
| |
| var->type = glsl_type::get_array_instance(lhs->type->fields.array, |
| rhs->type->array_size()); |
| d->type = var->type; |
| } |
| if (lhs->type->is_array()) { |
| mark_whole_array_access(rhs); |
| mark_whole_array_access(lhs); |
| } |
| } |
| |
| /* Most callers of do_assignment (assign, add_assign, pre_inc/dec, |
| * but not post_inc) need the converted assigned value as an rvalue |
| * to handle things like: |
| * |
| * i = j += 1; |
| */ |
| if (needs_rvalue) { |
| ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp", |
| ir_var_temporary); |
| instructions->push_tail(var); |
| instructions->push_tail(assign(var, rhs)); |
| |
| if (!error_emitted) { |
| ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var); |
| instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var)); |
| } |
| ir_rvalue *rvalue = new(ctx) ir_dereference_variable(var); |
| |
| if (extract_channel) { |
| rvalue = new(ctx) ir_expression(ir_binop_vector_extract, |
| rvalue, |
| extract_channel->clone(ctx, NULL)); |
| } |
| |
| *out_rvalue = rvalue; |
| } else { |
| if (!error_emitted) |
| instructions->push_tail(new(ctx) ir_assignment(lhs, rhs)); |
| *out_rvalue = NULL; |
| } |
| |
| return error_emitted; |
| } |
| |
| static ir_rvalue * |
| get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue) |
| { |
| void *ctx = ralloc_parent(lvalue); |
| ir_variable *var; |
| |
| var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp", |
| ir_var_temporary); |
| instructions->push_tail(var); |
| |
| instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var), |
| lvalue)); |
| |
| return new(ctx) ir_dereference_variable(var); |
| } |
| |
| |
| ir_rvalue * |
| ast_node::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) |
| { |
| (void) instructions; |
| (void) state; |
| |
| return NULL; |
| } |
| |
| void |
| ast_function_expression::hir_no_rvalue(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| (void)hir(instructions, state); |
| } |
| |
| void |
| ast_aggregate_initializer::hir_no_rvalue(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| (void)hir(instructions, state); |
| } |
| |
| static ir_rvalue * |
| do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) |
| { |
| int join_op; |
| ir_rvalue *cmp = NULL; |
| |
| if (operation == ir_binop_all_equal) |
| join_op = ir_binop_logic_and; |
| else |
| join_op = ir_binop_logic_or; |
| |
| switch (op0->type->base_type) { |
| case GLSL_TYPE_FLOAT: |
| case GLSL_TYPE_UINT: |
| case GLSL_TYPE_INT: |
| case GLSL_TYPE_BOOL: |
| case GLSL_TYPE_DOUBLE: |
| return new(mem_ctx) ir_expression(operation, op0, op1); |
| |
| case GLSL_TYPE_ARRAY: { |
| for (unsigned int i = 0; i < op0->type->length; i++) { |
| ir_rvalue *e0, *e1, *result; |
| |
| e0 = new(mem_ctx) ir_dereference_array(op0->clone(mem_ctx, NULL), |
| new(mem_ctx) ir_constant(i)); |
| e1 = new(mem_ctx) ir_dereference_array(op1->clone(mem_ctx, NULL), |
| new(mem_ctx) ir_constant(i)); |
| result = do_comparison(mem_ctx, operation, e0, e1); |
| |
| if (cmp) { |
| cmp = new(mem_ctx) ir_expression(join_op, cmp, result); |
| } else { |
| cmp = result; |
| } |
| } |
| |
| mark_whole_array_access(op0); |
| mark_whole_array_access(op1); |
| break; |
| } |
| |
| case GLSL_TYPE_STRUCT: { |
| for (unsigned int i = 0; i < op0->type->length; i++) { |
| ir_rvalue *e0, *e1, *result; |
| const char *field_name = op0->type->fields.structure[i].name; |
| |
| e0 = new(mem_ctx) ir_dereference_record(op0->clone(mem_ctx, NULL), |
| field_name); |
| e1 = new(mem_ctx) ir_dereference_record(op1->clone(mem_ctx, NULL), |
| field_name); |
| result = do_comparison(mem_ctx, operation, e0, e1); |
| |
| if (cmp) { |
| cmp = new(mem_ctx) ir_expression(join_op, cmp, result); |
| } else { |
| cmp = result; |
| } |
| } |
| break; |
| } |
| |
| case GLSL_TYPE_ERROR: |
| case GLSL_TYPE_VOID: |
| case GLSL_TYPE_SAMPLER: |
| case GLSL_TYPE_IMAGE: |
| case GLSL_TYPE_INTERFACE: |
| case GLSL_TYPE_ATOMIC_UINT: |
| case GLSL_TYPE_SUBROUTINE: |
| /* I assume a comparison of a struct containing a sampler just |
| * ignores the sampler present in the type. |
| */ |
| break; |
| } |
| |
| if (cmp == NULL) |
| cmp = new(mem_ctx) ir_constant(true); |
| |
| return cmp; |
| } |
| |
| /* For logical operations, we want to ensure that the operands are |
| * scalar booleans. If it isn't, emit an error and return a constant |
| * boolean to avoid triggering cascading error messages. |
| */ |
| ir_rvalue * |
| get_scalar_boolean_operand(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state, |
| ast_expression *parent_expr, |
| int operand, |
| const char *operand_name, |
| bool *error_emitted) |
| { |
| ast_expression *expr = parent_expr->subexpressions[operand]; |
| void *ctx = state; |
| ir_rvalue *val = expr->hir(instructions, state); |
| |
| if (val->type->is_boolean() && val->type->is_scalar()) |
| return val; |
| |
| if (!*error_emitted) { |
| YYLTYPE loc = expr->get_location(); |
| _mesa_glsl_error(&loc, state, "%s of `%s' must be scalar boolean", |
| operand_name, |
| parent_expr->operator_string(parent_expr->oper)); |
| *error_emitted = true; |
| } |
| |
| return new(ctx) ir_constant(true); |
| } |
| |
| /** |
| * If name refers to a builtin array whose maximum allowed size is less than |
| * size, report an error and return true. Otherwise return false. |
| */ |
| void |
| check_builtin_array_max_size(const char *name, unsigned size, |
| YYLTYPE loc, struct _mesa_glsl_parse_state *state) |
| { |
| if ((strcmp("gl_TexCoord", name) == 0) |
| && (size > state->Const.MaxTextureCoords)) { |
| /* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec: |
| * |
| * "The size [of gl_TexCoord] can be at most |
| * gl_MaxTextureCoords." |
| */ |
| _mesa_glsl_error(&loc, state, "`gl_TexCoord' array size cannot " |
| "be larger than gl_MaxTextureCoords (%u)", |
| state->Const.MaxTextureCoords); |
| } else if (strcmp("gl_ClipDistance", name) == 0 |
| && size > state->Const.MaxClipPlanes) { |
| /* From section 7.1 (Vertex Shader Special Variables) of the |
| * GLSL 1.30 spec: |
| * |
| * "The gl_ClipDistance array is predeclared as unsized and |
| * must be sized by the shader either redeclaring it with a |
| * size or indexing it only with integral constant |
| * expressions. ... The size can be at most |
| * gl_MaxClipDistances." |
| */ |
| _mesa_glsl_error(&loc, state, "`gl_ClipDistance' array size cannot " |
| "be larger than gl_MaxClipDistances (%u)", |
| state->Const.MaxClipPlanes); |
| } |
| } |
| |
| /** |
| * Create the constant 1, of a which is appropriate for incrementing and |
| * decrementing values of the given GLSL type. For example, if type is vec4, |
| * this creates a constant value of 1.0 having type float. |
| * |
| * If the given type is invalid for increment and decrement operators, return |
| * a floating point 1--the error will be detected later. |
| */ |
| static ir_rvalue * |
| constant_one_for_inc_dec(void *ctx, const glsl_type *type) |
| { |
| switch (type->base_type) { |
| case GLSL_TYPE_UINT: |
| return new(ctx) ir_constant((unsigned) 1); |
| case GLSL_TYPE_INT: |
| return new(ctx) ir_constant(1); |
| default: |
| case GLSL_TYPE_FLOAT: |
| return new(ctx) ir_constant(1.0f); |
| } |
| } |
| |
| ir_rvalue * |
| ast_expression::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| return do_hir(instructions, state, true); |
| } |
| |
| void |
| ast_expression::hir_no_rvalue(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| do_hir(instructions, state, false); |
| } |
| |
| ir_rvalue * |
| ast_expression::do_hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state, |
| bool needs_rvalue) |
| { |
| void *ctx = state; |
| static const int operations[AST_NUM_OPERATORS] = { |
| -1, /* ast_assign doesn't convert to ir_expression. */ |
| -1, /* ast_plus doesn't convert to ir_expression. */ |
| ir_unop_neg, |
| ir_binop_add, |
| ir_binop_sub, |
| ir_binop_mul, |
| ir_binop_div, |
| ir_binop_mod, |
| ir_binop_lshift, |
| ir_binop_rshift, |
| ir_binop_less, |
| ir_binop_greater, |
| ir_binop_lequal, |
| ir_binop_gequal, |
| ir_binop_all_equal, |
| ir_binop_any_nequal, |
| ir_binop_bit_and, |
| ir_binop_bit_xor, |
| ir_binop_bit_or, |
| ir_unop_bit_not, |
| ir_binop_logic_and, |
| ir_binop_logic_xor, |
| ir_binop_logic_or, |
| ir_unop_logic_not, |
| |
| /* Note: The following block of expression types actually convert |
| * to multiple IR instructions. |
| */ |
| ir_binop_mul, /* ast_mul_assign */ |
| ir_binop_div, /* ast_div_assign */ |
| ir_binop_mod, /* ast_mod_assign */ |
| ir_binop_add, /* ast_add_assign */ |
| ir_binop_sub, /* ast_sub_assign */ |
| ir_binop_lshift, /* ast_ls_assign */ |
| ir_binop_rshift, /* ast_rs_assign */ |
| ir_binop_bit_and, /* ast_and_assign */ |
| ir_binop_bit_xor, /* ast_xor_assign */ |
| ir_binop_bit_or, /* ast_or_assign */ |
| |
| -1, /* ast_conditional doesn't convert to ir_expression. */ |
| ir_binop_add, /* ast_pre_inc. */ |
| ir_binop_sub, /* ast_pre_dec. */ |
| ir_binop_add, /* ast_post_inc. */ |
| ir_binop_sub, /* ast_post_dec. */ |
| -1, /* ast_field_selection doesn't conv to ir_expression. */ |
| -1, /* ast_array_index doesn't convert to ir_expression. */ |
| -1, /* ast_function_call doesn't conv to ir_expression. */ |
| -1, /* ast_identifier doesn't convert to ir_expression. */ |
| -1, /* ast_int_constant doesn't convert to ir_expression. */ |
| -1, /* ast_uint_constant doesn't conv to ir_expression. */ |
| -1, /* ast_float_constant doesn't conv to ir_expression. */ |
| -1, /* ast_bool_constant doesn't conv to ir_expression. */ |
| -1, /* ast_sequence doesn't convert to ir_expression. */ |
| }; |
| ir_rvalue *result = NULL; |
| ir_rvalue *op[3]; |
| const struct glsl_type *type; /* a temporary variable for switch cases */ |
| bool error_emitted = false; |
| YYLTYPE loc; |
| |
| loc = this->get_location(); |
| |
| switch (this->oper) { |
| case ast_aggregate: |
| assert(!"ast_aggregate: Should never get here."); |
| break; |
| |
| case ast_assign: { |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = this->subexpressions[1]->hir(instructions, state); |
| |
| error_emitted = |
| do_assignment(instructions, state, |
| this->subexpressions[0]->non_lvalue_description, |
| op[0], op[1], &result, needs_rvalue, false, |
| this->subexpressions[0]->get_location()); |
| break; |
| } |
| |
| case ast_plus: |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| |
| type = unary_arithmetic_result_type(op[0]->type, state, & loc); |
| |
| error_emitted = type->is_error(); |
| |
| result = op[0]; |
| break; |
| |
| case ast_neg: |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| |
| type = unary_arithmetic_result_type(op[0]->type, state, & loc); |
| |
| error_emitted = type->is_error(); |
| |
| result = new(ctx) ir_expression(operations[this->oper], type, |
| op[0], NULL); |
| break; |
| |
| case ast_add: |
| case ast_sub: |
| case ast_mul: |
| case ast_div: |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = this->subexpressions[1]->hir(instructions, state); |
| |
| type = arithmetic_result_type(op[0], op[1], |
| (this->oper == ast_mul), |
| state, & loc); |
| error_emitted = type->is_error(); |
| |
| result = new(ctx) ir_expression(operations[this->oper], type, |
| op[0], op[1]); |
| break; |
| |
| case ast_mod: |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = this->subexpressions[1]->hir(instructions, state); |
| |
| type = modulus_result_type(op[0]->type, op[1]->type, state, & loc); |
| |
| assert(operations[this->oper] == ir_binop_mod); |
| |
| result = new(ctx) ir_expression(operations[this->oper], type, |
| op[0], op[1]); |
| error_emitted = type->is_error(); |
| break; |
| |
| case ast_lshift: |
| case ast_rshift: |
| if (!state->check_bitwise_operations_allowed(&loc)) { |
| error_emitted = true; |
| } |
| |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = this->subexpressions[1]->hir(instructions, state); |
| type = shift_result_type(op[0]->type, op[1]->type, this->oper, state, |
| &loc); |
| result = new(ctx) ir_expression(operations[this->oper], type, |
| op[0], op[1]); |
| error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); |
| break; |
| |
| case ast_less: |
| case ast_greater: |
| case ast_lequal: |
| case ast_gequal: |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = this->subexpressions[1]->hir(instructions, state); |
| |
| type = relational_result_type(op[0], op[1], state, & loc); |
| |
| /* The relational operators must either generate an error or result |
| * in a scalar boolean. See page 57 of the GLSL 1.50 spec. |
| */ |
| assert(type->is_error() |
| || ((type->base_type == GLSL_TYPE_BOOL) |
| && type->is_scalar())); |
| |
| result = new(ctx) ir_expression(operations[this->oper], type, |
| op[0], op[1]); |
| error_emitted = type->is_error(); |
| break; |
| |
| case ast_nequal: |
| case ast_equal: |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = this->subexpressions[1]->hir(instructions, state); |
| |
| /* From page 58 (page 64 of the PDF) of the GLSL 1.50 spec: |
| * |
| * "The equality operators equal (==), and not equal (!=) |
| * operate on all types. They result in a scalar Boolean. If |
| * the operand types do not match, then there must be a |
| * conversion from Section 4.1.10 "Implicit Conversions" |
| * applied to one operand that can make them match, in which |
| * case this conversion is done." |
| */ |
| |
| if (op[0]->type == glsl_type::void_type || op[1]->type == glsl_type::void_type) { |
| _mesa_glsl_error(& loc, state, "`%s': wrong operand types: " |
| "no operation `%1$s' exists that takes a left-hand " |
| "operand of type 'void' or a right operand of type " |
| "'void'", (this->oper == ast_equal) ? "==" : "!="); |
| error_emitted = true; |
| } else if ((!apply_implicit_conversion(op[0]->type, op[1], state) |
| && !apply_implicit_conversion(op[1]->type, op[0], state)) |
| || (op[0]->type != op[1]->type)) { |
| _mesa_glsl_error(& loc, state, "operands of `%s' must have the same " |
| "type", (this->oper == ast_equal) ? "==" : "!="); |
| error_emitted = true; |
| } else if ((op[0]->type->is_array() || op[1]->type->is_array()) && |
| !state->check_version(120, 300, &loc, |
| "array comparisons forbidden")) { |
| error_emitted = true; |
| } else if ((op[0]->type->contains_opaque() || |
| op[1]->type->contains_opaque())) { |
| _mesa_glsl_error(&loc, state, "opaque type comparisons forbidden"); |
| error_emitted = true; |
| } |
| |
| if (error_emitted) { |
| result = new(ctx) ir_constant(false); |
| } else { |
| result = do_comparison(ctx, operations[this->oper], op[0], op[1]); |
| assert(result->type == glsl_type::bool_type); |
| } |
| break; |
| |
| case ast_bit_and: |
| case ast_bit_xor: |
| case ast_bit_or: |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = this->subexpressions[1]->hir(instructions, state); |
| type = bit_logic_result_type(op[0]->type, op[1]->type, this->oper, |
| state, &loc); |
| result = new(ctx) ir_expression(operations[this->oper], type, |
| op[0], op[1]); |
| error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); |
| break; |
| |
| case ast_bit_not: |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| |
| if (!state->check_bitwise_operations_allowed(&loc)) { |
| error_emitted = true; |
| } |
| |
| if (!op[0]->type->is_integer()) { |
| _mesa_glsl_error(&loc, state, "operand of `~' must be an integer"); |
| error_emitted = true; |
| } |
| |
| type = error_emitted ? glsl_type::error_type : op[0]->type; |
| result = new(ctx) ir_expression(ir_unop_bit_not, type, op[0], NULL); |
| break; |
| |
| case ast_logic_and: { |
| exec_list rhs_instructions; |
| op[0] = get_scalar_boolean_operand(instructions, state, this, 0, |
| "LHS", &error_emitted); |
| op[1] = get_scalar_boolean_operand(&rhs_instructions, state, this, 1, |
| "RHS", &error_emitted); |
| |
| if (rhs_instructions.is_empty()) { |
| result = new(ctx) ir_expression(ir_binop_logic_and, op[0], op[1]); |
| type = result->type; |
| } else { |
| ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type, |
| "and_tmp", |
| ir_var_temporary); |
| instructions->push_tail(tmp); |
| |
| ir_if *const stmt = new(ctx) ir_if(op[0]); |
| instructions->push_tail(stmt); |
| |
| stmt->then_instructions.append_list(&rhs_instructions); |
| ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp); |
| ir_assignment *const then_assign = |
| new(ctx) ir_assignment(then_deref, op[1]); |
| stmt->then_instructions.push_tail(then_assign); |
| |
| ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp); |
| ir_assignment *const else_assign = |
| new(ctx) ir_assignment(else_deref, new(ctx) ir_constant(false)); |
| stmt->else_instructions.push_tail(else_assign); |
| |
| result = new(ctx) ir_dereference_variable(tmp); |
| type = tmp->type; |
| } |
| break; |
| } |
| |
| case ast_logic_or: { |
| exec_list rhs_instructions; |
| op[0] = get_scalar_boolean_operand(instructions, state, this, 0, |
| "LHS", &error_emitted); |
| op[1] = get_scalar_boolean_operand(&rhs_instructions, state, this, 1, |
| "RHS", &error_emitted); |
| |
| if (rhs_instructions.is_empty()) { |
| result = new(ctx) ir_expression(ir_binop_logic_or, op[0], op[1]); |
| type = result->type; |
| } else { |
| ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type, |
| "or_tmp", |
| ir_var_temporary); |
| instructions->push_tail(tmp); |
| |
| ir_if *const stmt = new(ctx) ir_if(op[0]); |
| instructions->push_tail(stmt); |
| |
| ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp); |
| ir_assignment *const then_assign = |
| new(ctx) ir_assignment(then_deref, new(ctx) ir_constant(true)); |
| stmt->then_instructions.push_tail(then_assign); |
| |
| stmt->else_instructions.append_list(&rhs_instructions); |
| ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp); |
| ir_assignment *const else_assign = |
| new(ctx) ir_assignment(else_deref, op[1]); |
| stmt->else_instructions.push_tail(else_assign); |
| |
| result = new(ctx) ir_dereference_variable(tmp); |
| type = tmp->type; |
| } |
| break; |
| } |
| |
| case ast_logic_xor: |
| /* From page 33 (page 39 of the PDF) of the GLSL 1.10 spec: |
| * |
| * "The logical binary operators and (&&), or ( | | ), and |
| * exclusive or (^^). They operate only on two Boolean |
| * expressions and result in a Boolean expression." |
| */ |
| op[0] = get_scalar_boolean_operand(instructions, state, this, 0, "LHS", |
| &error_emitted); |
| op[1] = get_scalar_boolean_operand(instructions, state, this, 1, "RHS", |
| &error_emitted); |
| |
| result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type, |
| op[0], op[1]); |
| break; |
| |
| case ast_logic_not: |
| op[0] = get_scalar_boolean_operand(instructions, state, this, 0, |
| "operand", &error_emitted); |
| |
| result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type, |
| op[0], NULL); |
| break; |
| |
| case ast_mul_assign: |
| case ast_div_assign: |
| case ast_add_assign: |
| case ast_sub_assign: { |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = this->subexpressions[1]->hir(instructions, state); |
| |
| type = arithmetic_result_type(op[0], op[1], |
| (this->oper == ast_mul_assign), |
| state, & loc); |
| |
| ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], type, |
| op[0], op[1]); |
| |
| error_emitted = |
| do_assignment(instructions, state, |
| this->subexpressions[0]->non_lvalue_description, |
| op[0]->clone(ctx, NULL), temp_rhs, |
| &result, needs_rvalue, false, |
| this->subexpressions[0]->get_location()); |
| |
| /* GLSL 1.10 does not allow array assignment. However, we don't have to |
| * explicitly test for this because none of the binary expression |
| * operators allow array operands either. |
| */ |
| |
| break; |
| } |
| |
| case ast_mod_assign: { |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = this->subexpressions[1]->hir(instructions, state); |
| |
| type = modulus_result_type(op[0]->type, op[1]->type, state, & loc); |
| |
| assert(operations[this->oper] == ir_binop_mod); |
| |
| ir_rvalue *temp_rhs; |
| temp_rhs = new(ctx) ir_expression(operations[this->oper], type, |
| op[0], op[1]); |
| |
| error_emitted = |
| do_assignment(instructions, state, |
| this->subexpressions[0]->non_lvalue_description, |
| op[0]->clone(ctx, NULL), temp_rhs, |
| &result, needs_rvalue, false, |
| this->subexpressions[0]->get_location()); |
| break; |
| } |
| |
| case ast_ls_assign: |
| case ast_rs_assign: { |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = this->subexpressions[1]->hir(instructions, state); |
| type = shift_result_type(op[0]->type, op[1]->type, this->oper, state, |
| &loc); |
| ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], |
| type, op[0], op[1]); |
| error_emitted = |
| do_assignment(instructions, state, |
| this->subexpressions[0]->non_lvalue_description, |
| op[0]->clone(ctx, NULL), temp_rhs, |
| &result, needs_rvalue, false, |
| this->subexpressions[0]->get_location()); |
| break; |
| } |
| |
| case ast_and_assign: |
| case ast_xor_assign: |
| case ast_or_assign: { |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = this->subexpressions[1]->hir(instructions, state); |
| type = bit_logic_result_type(op[0]->type, op[1]->type, this->oper, |
| state, &loc); |
| ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], |
| type, op[0], op[1]); |
| error_emitted = |
| do_assignment(instructions, state, |
| this->subexpressions[0]->non_lvalue_description, |
| op[0]->clone(ctx, NULL), temp_rhs, |
| &result, needs_rvalue, false, |
| this->subexpressions[0]->get_location()); |
| break; |
| } |
| |
| case ast_conditional: { |
| /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec: |
| * |
| * "The ternary selection operator (?:). It operates on three |
| * expressions (exp1 ? exp2 : exp3). This operator evaluates the |
| * first expression, which must result in a scalar Boolean." |
| */ |
| op[0] = get_scalar_boolean_operand(instructions, state, this, 0, |
| "condition", &error_emitted); |
| |
| /* The :? operator is implemented by generating an anonymous temporary |
| * followed by an if-statement. The last instruction in each branch of |
| * the if-statement assigns a value to the anonymous temporary. This |
| * temporary is the r-value of the expression. |
| */ |
| exec_list then_instructions; |
| exec_list else_instructions; |
| |
| op[1] = this->subexpressions[1]->hir(&then_instructions, state); |
| op[2] = this->subexpressions[2]->hir(&else_instructions, state); |
| |
| /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec: |
| * |
| * "The second and third expressions can be any type, as |
| * long their types match, or there is a conversion in |
| * Section 4.1.10 "Implicit Conversions" that can be applied |
| * to one of the expressions to make their types match. This |
| * resulting matching type is the type of the entire |
| * expression." |
| */ |
| if ((!apply_implicit_conversion(op[1]->type, op[2], state) |
| && !apply_implicit_conversion(op[2]->type, op[1], state)) |
| || (op[1]->type != op[2]->type)) { |
| YYLTYPE loc = this->subexpressions[1]->get_location(); |
| |
| _mesa_glsl_error(& loc, state, "second and third operands of ?: " |
| "operator must have matching types"); |
| error_emitted = true; |
| type = glsl_type::error_type; |
| } else { |
| type = op[1]->type; |
| } |
| |
| /* From page 33 (page 39 of the PDF) of the GLSL 1.10 spec: |
| * |
| * "The second and third expressions must be the same type, but can |
| * be of any type other than an array." |
| */ |
| if (type->is_array() && |
| !state->check_version(120, 300, &loc, |
| "second and third operands of ?: operator " |
| "cannot be arrays")) { |
| error_emitted = true; |
| } |
| |
| /* From section 4.1.7 of the GLSL 4.50 spec (Opaque Types): |
| * |
| * "Except for array indexing, structure member selection, and |
| * parentheses, opaque variables are not allowed to be operands in |
| * expressions; such use results in a compile-time error." |
| */ |
| if (type->contains_opaque()) { |
| _mesa_glsl_error(&loc, state, "opaque variables cannot be operands " |
| "of the ?: operator"); |
| error_emitted = true; |
| } |
| |
| ir_constant *cond_val = op[0]->constant_expression_value(); |
| |
| if (then_instructions.is_empty() |
| && else_instructions.is_empty() |
| && cond_val != NULL) { |
| result = cond_val->value.b[0] ? op[1] : op[2]; |
| } else { |
| /* The copy to conditional_tmp reads the whole array. */ |
| if (type->is_array()) { |
| mark_whole_array_access(op[1]); |
| mark_whole_array_access(op[2]); |
| } |
| |
| ir_variable *const tmp = |
| new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary); |
| instructions->push_tail(tmp); |
| |
| ir_if *const stmt = new(ctx) ir_if(op[0]); |
| instructions->push_tail(stmt); |
| |
| then_instructions.move_nodes_to(& stmt->then_instructions); |
| ir_dereference *const then_deref = |
| new(ctx) ir_dereference_variable(tmp); |
| ir_assignment *const then_assign = |
| new(ctx) ir_assignment(then_deref, op[1]); |
| stmt->then_instructions.push_tail(then_assign); |
| |
| else_instructions.move_nodes_to(& stmt->else_instructions); |
| ir_dereference *const else_deref = |
| new(ctx) ir_dereference_variable(tmp); |
| ir_assignment *const else_assign = |
| new(ctx) ir_assignment(else_deref, op[2]); |
| stmt->else_instructions.push_tail(else_assign); |
| |
| result = new(ctx) ir_dereference_variable(tmp); |
| } |
| break; |
| } |
| |
| case ast_pre_inc: |
| case ast_pre_dec: { |
| this->non_lvalue_description = (this->oper == ast_pre_inc) |
| ? "pre-increment operation" : "pre-decrement operation"; |
| |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = constant_one_for_inc_dec(ctx, op[0]->type); |
| |
| type = arithmetic_result_type(op[0], op[1], false, state, & loc); |
| |
| ir_rvalue *temp_rhs; |
| temp_rhs = new(ctx) ir_expression(operations[this->oper], type, |
| op[0], op[1]); |
| |
| error_emitted = |
| do_assignment(instructions, state, |
| this->subexpressions[0]->non_lvalue_description, |
| op[0]->clone(ctx, NULL), temp_rhs, |
| &result, needs_rvalue, false, |
| this->subexpressions[0]->get_location()); |
| break; |
| } |
| |
| case ast_post_inc: |
| case ast_post_dec: { |
| this->non_lvalue_description = (this->oper == ast_post_inc) |
| ? "post-increment operation" : "post-decrement operation"; |
| op[0] = this->subexpressions[0]->hir(instructions, state); |
| op[1] = constant_one_for_inc_dec(ctx, op[0]->type); |
| |
| error_emitted = op[0]->type->is_error() || op[1]->type->is_error(); |
| |
| type = arithmetic_result_type(op[0], op[1], false, state, & loc); |
| |
| ir_rvalue *temp_rhs; |
| temp_rhs = new(ctx) ir_expression(operations[this->oper], type, |
| op[0], op[1]); |
| |
| /* Get a temporary of a copy of the lvalue before it's modified. |
| * This may get thrown away later. |
| */ |
| result = get_lvalue_copy(instructions, op[0]->clone(ctx, NULL)); |
| |
| ir_rvalue *junk_rvalue; |
| error_emitted = |
| do_assignment(instructions, state, |
| this->subexpressions[0]->non_lvalue_description, |
| op[0]->clone(ctx, NULL), temp_rhs, |
| &junk_rvalue, false, false, |
| this->subexpressions[0]->get_location()); |
| |
| break; |
| } |
| |
| case ast_field_selection: |
| result = _mesa_ast_field_selection_to_hir(this, instructions, state); |
| break; |
| |
| case ast_array_index: { |
| YYLTYPE index_loc = subexpressions[1]->get_location(); |
| |
| op[0] = subexpressions[0]->hir(instructions, state); |
| op[1] = subexpressions[1]->hir(instructions, state); |
| |
| result = _mesa_ast_array_index_to_hir(ctx, state, op[0], op[1], |
| loc, index_loc); |
| |
| if (result->type->is_error()) |
| error_emitted = true; |
| |
| break; |
| } |
| |
| case ast_function_call: |
| /* Should *NEVER* get here. ast_function_call should always be handled |
| * by ast_function_expression::hir. |
| */ |
| assert(0); |
| break; |
| |
| case ast_identifier: { |
| /* ast_identifier can appear several places in a full abstract syntax |
| * tree. This particular use must be at location specified in the grammar |
| * as 'variable_identifier'. |
| */ |
| ir_variable *var = |
| state->symbols->get_variable(this->primary_expression.identifier); |
| |
| if (var != NULL) { |
| var->data.used = true; |
| result = new(ctx) ir_dereference_variable(var); |
| } else { |
| _mesa_glsl_error(& loc, state, "`%s' undeclared", |
| this->primary_expression.identifier); |
| |
| result = ir_rvalue::error_value(ctx); |
| error_emitted = true; |
| } |
| break; |
| } |
| |
| case ast_int_constant: |
| result = new(ctx) ir_constant(this->primary_expression.int_constant); |
| break; |
| |
| case ast_uint_constant: |
| result = new(ctx) ir_constant(this->primary_expression.uint_constant); |
| break; |
| |
| case ast_float_constant: |
| result = new(ctx) ir_constant(this->primary_expression.float_constant); |
| break; |
| |
| case ast_bool_constant: |
| result = new(ctx) ir_constant(bool(this->primary_expression.bool_constant)); |
| break; |
| |
| case ast_double_constant: |
| result = new(ctx) ir_constant(this->primary_expression.double_constant); |
| break; |
| |
| case ast_sequence: { |
| /* It should not be possible to generate a sequence in the AST without |
| * any expressions in it. |
| */ |
| assert(!this->expressions.is_empty()); |
| |
| /* The r-value of a sequence is the last expression in the sequence. If |
| * the other expressions in the sequence do not have side-effects (and |
| * therefore add instructions to the instruction list), they get dropped |
| * on the floor. |
| */ |
| exec_node *previous_tail_pred = NULL; |
| YYLTYPE previous_operand_loc = loc; |
| |
| foreach_list_typed (ast_node, ast, link, &this->expressions) { |
| /* If one of the operands of comma operator does not generate any |
| * code, we want to emit a warning. At each pass through the loop |
| * previous_tail_pred will point to the last instruction in the |
| * stream *before* processing the previous operand. Naturally, |
| * instructions->tail_pred will point to the last instruction in the |
| * stream *after* processing the previous operand. If the two |
| * pointers match, then the previous operand had no effect. |
| * |
| * The warning behavior here differs slightly from GCC. GCC will |
| * only emit a warning if none of the left-hand operands have an |
| * effect. However, it will emit a warning for each. I believe that |
| * there are some cases in C (especially with GCC extensions) where |
| * it is useful to have an intermediate step in a sequence have no |
| * effect, but I don't think these cases exist in GLSL. Either way, |
| * it would be a giant hassle to replicate that behavior. |
| */ |
| if (previous_tail_pred == instructions->tail_pred) { |
| _mesa_glsl_warning(&previous_operand_loc, state, |
| "left-hand operand of comma expression has " |
| "no effect"); |
| } |
| |
| /* tail_pred is directly accessed instead of using the get_tail() |
| * method for performance reasons. get_tail() has extra code to |
| * return NULL when the list is empty. We don't care about that |
| * here, so using tail_pred directly is fine. |
| */ |
| previous_tail_pred = instructions->tail_pred; |
| previous_operand_loc = ast->get_location(); |
| |
| result = ast->hir(instructions, state); |
| } |
| |
| /* Any errors should have already been emitted in the loop above. |
| */ |
| error_emitted = true; |
| break; |
| } |
| } |
| type = NULL; /* use result->type, not type. */ |
| assert(result != NULL || !needs_rvalue); |
| |
| if (result && result->type->is_error() && !error_emitted) |
| _mesa_glsl_error(& loc, state, "type mismatch"); |
| |
| return result; |
| } |
| |
| |
| ir_rvalue * |
| ast_expression_statement::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| /* It is possible to have expression statements that don't have an |
| * expression. This is the solitary semicolon: |
| * |
| * for (i = 0; i < 5; i++) |
| * ; |
| * |
| * In this case the expression will be NULL. Test for NULL and don't do |
| * anything in that case. |
| */ |
| if (expression != NULL) |
| expression->hir_no_rvalue(instructions, state); |
| |
| /* Statements do not have r-values. |
| */ |
| return NULL; |
| } |
| |
| |
| ir_rvalue * |
| ast_compound_statement::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| if (new_scope) |
| state->symbols->push_scope(); |
| |
| foreach_list_typed (ast_node, ast, link, &this->statements) |
| ast->hir(instructions, state); |
| |
| if (new_scope) |
| state->symbols->pop_scope(); |
| |
| /* Compound statements do not have r-values. |
| */ |
| return NULL; |
| } |
| |
| /** |
| * Evaluate the given exec_node (which should be an ast_node representing |
| * a single array dimension) and return its integer value. |
| */ |
| static unsigned |
| process_array_size(exec_node *node, |
| struct _mesa_glsl_parse_state *state) |
| { |
| exec_list dummy_instructions; |
| |
| ast_node *array_size = exec_node_data(ast_node, node, link); |
| ir_rvalue *const ir = array_size->hir(& dummy_instructions, state); |
| YYLTYPE loc = array_size->get_location(); |
| |
| if (ir == NULL) { |
| _mesa_glsl_error(& loc, state, |
| "array size could not be resolved"); |
| return 0; |
| } |
| |
| if (!ir->type->is_integer()) { |
| _mesa_glsl_error(& loc, state, |
| "array size must be integer type"); |
| return 0; |
| } |
| |
| if (!ir->type->is_scalar()) { |
| _mesa_glsl_error(& loc, state, |
| "array size must be scalar type"); |
| return 0; |
| } |
| |
| ir_constant *const size = ir->constant_expression_value(); |
| if (size == NULL) { |
| _mesa_glsl_error(& loc, state, "array size must be a " |
| "constant valued expression"); |
| return 0; |
| } |
| |
| if (size->value.i[0] <= 0) { |
| _mesa_glsl_error(& loc, state, "array size must be > 0"); |
| return 0; |
| } |
| |
| assert(size->type == ir->type); |
| |
| /* If the array size is const (and we've verified that |
| * it is) then no instructions should have been emitted |
| * when we converted it to HIR. If they were emitted, |
| * then either the array size isn't const after all, or |
| * we are emitting unnecessary instructions. |
| */ |
| assert(dummy_instructions.is_empty()); |
| |
| return size->value.u[0]; |
| } |
| |
| static const glsl_type * |
| process_array_type(YYLTYPE *loc, const glsl_type *base, |
| ast_array_specifier *array_specifier, |
| struct _mesa_glsl_parse_state *state) |
| { |
| const glsl_type *array_type = base; |
| |
| if (array_specifier != NULL) { |
| if (base->is_array()) { |
| |
| /* From page 19 (page 25) of the GLSL 1.20 spec: |
| * |
| * "Only one-dimensional arrays may be declared." |
| */ |
| if (!state->ARB_arrays_of_arrays_enable) { |
| _mesa_glsl_error(loc, state, |
| "invalid array of `%s'" |
| "GL_ARB_arrays_of_arrays " |
| "required for defining arrays of arrays", |
| base->name); |
| return glsl_type::error_type; |
| } |
| |
| if (base->length == 0) { |
| _mesa_glsl_error(loc, state, |
| "only the outermost array dimension can " |
| "be unsized", |
| base->name); |
| return glsl_type::error_type; |
| } |
| } |
| |
| for (exec_node *node = array_specifier->array_dimensions.tail_pred; |
| !node->is_head_sentinel(); node = node->prev) { |
| unsigned array_size = process_array_size(node, state); |
| array_type = glsl_type::get_array_instance(array_type, array_size); |
| } |
| |
| if (array_specifier->is_unsized_array) |
| array_type = glsl_type::get_array_instance(array_type, 0); |
| } |
| |
| return array_type; |
| } |
| |
| |
| const glsl_type * |
| ast_type_specifier::glsl_type(const char **name, |
| struct _mesa_glsl_parse_state *state) const |
| { |
| const struct glsl_type *type; |
| |
| type = state->symbols->get_type(this->type_name); |
| *name = this->type_name; |
| |
| YYLTYPE loc = this->get_location(); |
| type = process_array_type(&loc, type, this->array_specifier, state); |
| |
| return type; |
| } |
| |
| const glsl_type * |
| ast_fully_specified_type::glsl_type(const char **name, |
| struct _mesa_glsl_parse_state *state) const |
| { |
| const struct glsl_type *type = this->specifier->glsl_type(name, state); |
| |
| if (type == NULL) |
| return NULL; |
| |
| if (type->base_type == GLSL_TYPE_FLOAT |
| && state->es_shader |
| && state->stage == MESA_SHADER_FRAGMENT |
| && this->qualifier.precision == ast_precision_none |
| && state->symbols->get_variable("#default precision") == NULL) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(&loc, state, |
| "no precision specified this scope for type `%s'", |
| type->name); |
| } |
| |
| return type; |
| } |
| |
| /** |
| * Determine whether a toplevel variable declaration declares a varying. This |
| * function operates by examining the variable's mode and the shader target, |
| * so it correctly identifies linkage variables regardless of whether they are |
| * declared using the deprecated "varying" syntax or the new "in/out" syntax. |
| * |
| * Passing a non-toplevel variable declaration (e.g. a function parameter) to |
| * this function will produce undefined results. |
| */ |
| static bool |
| is_varying_var(ir_variable *var, gl_shader_stage target) |
| { |
| switch (target) { |
| case MESA_SHADER_VERTEX: |
| return var->data.mode == ir_var_shader_out; |
| case MESA_SHADER_FRAGMENT: |
| return var->data.mode == ir_var_shader_in; |
| default: |
| return var->data.mode == ir_var_shader_out || var->data.mode == ir_var_shader_in; |
| } |
| } |
| |
| |
| /** |
| * Matrix layout qualifiers are only allowed on certain types |
| */ |
| static void |
| validate_matrix_layout_for_type(struct _mesa_glsl_parse_state *state, |
| YYLTYPE *loc, |
| const glsl_type *type, |
| ir_variable *var) |
| { |
| if (var && !var->is_in_buffer_block()) { |
| /* Layout qualifiers may only apply to interface blocks and fields in |
| * them. |
| */ |
| _mesa_glsl_error(loc, state, |
| "uniform block layout qualifiers row_major and " |
| "column_major may not be applied to variables " |
| "outside of uniform blocks"); |
| } else if (!type->is_matrix()) { |
| /* The OpenGL ES 3.0 conformance tests did not originally allow |
| * matrix layout qualifiers on non-matrices. However, the OpenGL |
| * 4.4 and OpenGL ES 3.0 (revision TBD) specifications were |
| * amended to specifically allow these layouts on all types. Emit |
| * a warning so that people know their code may not be portable. |
| */ |
| _mesa_glsl_warning(loc, state, |
| "uniform block layout qualifiers row_major and " |
| "column_major applied to non-matrix types may " |
| "be rejected by older compilers"); |
| } else if (type->is_record()) { |
| /* We allow 'layout(row_major)' on structure types because it's the only |
| * way to get row-major layouts on matrices contained in structures. |
| */ |
| _mesa_glsl_warning(loc, state, |
| "uniform block layout qualifiers row_major and " |
| "column_major applied to structure types is not " |
| "strictly conformant and may be rejected by other " |
| "compilers"); |
| } |
| } |
| |
| static bool |
| validate_binding_qualifier(struct _mesa_glsl_parse_state *state, |
| YYLTYPE *loc, |
| const glsl_type *type, |
| const ast_type_qualifier *qual) |
| { |
| if (!qual->flags.q.uniform && !qual->flags.q.buffer) { |
| _mesa_glsl_error(loc, state, |
| "the \"binding\" qualifier only applies to uniforms and " |
| "shader storage buffer objects"); |
| return false; |
| } |
| |
| if (qual->binding < 0) { |
| _mesa_glsl_error(loc, state, "binding values must be >= 0"); |
| return false; |
| } |
| |
| const struct gl_context *const ctx = state->ctx; |
| unsigned elements = type->is_array() ? type->arrays_of_arrays_size() : 1; |
| unsigned max_index = qual->binding + elements - 1; |
| const glsl_type *base_type = type->without_array(); |
| |
| if (base_type->is_interface()) { |
| /* UBOs. From page 60 of the GLSL 4.20 specification: |
| * "If the binding point for any uniform block instance is less than zero, |
| * or greater than or equal to the implementation-dependent maximum |
| * number of uniform buffer bindings, a compilation error will occur. |
| * When the binding identifier is used with a uniform block instanced as |
| * an array of size N, all elements of the array from binding through |
| * binding + N – 1 must be within this range." |
| * |
| * The implementation-dependent maximum is GL_MAX_UNIFORM_BUFFER_BINDINGS. |
| */ |
| if (qual->flags.q.uniform && |
| max_index >= ctx->Const.MaxUniformBufferBindings) { |
| _mesa_glsl_error(loc, state, "layout(binding = %d) for %d UBOs exceeds " |
| "the maximum number of UBO binding points (%d)", |
| qual->binding, elements, |
| ctx->Const.MaxUniformBufferBindings); |
| return false; |
| } |
| |
| /* SSBOs. From page 67 of the GLSL 4.30 specification: |
| * "If the binding point for any uniform or shader storage block instance |
| * is less than zero, or greater than or equal to the |
| * implementation-dependent maximum number of uniform buffer bindings, a |
| * compile-time error will occur. When the binding identifier is used |
| * with a uniform or shader storage block instanced as an array of size |
| * N, all elements of the array from binding through binding + N – 1 must |
| * be within this range." |
| */ |
| if (qual->flags.q.buffer && |
| max_index >= ctx->Const.MaxShaderStorageBufferBindings) { |
| _mesa_glsl_error(loc, state, "layout(binding = %d) for %d SSBOs exceeds " |
| "the maximum number of SSBO binding points (%d)", |
| qual->binding, elements, |
| ctx->Const.MaxShaderStorageBufferBindings); |
| return false; |
| } |
| } else if (base_type->is_sampler()) { |
| /* Samplers. From page 63 of the GLSL 4.20 specification: |
| * "If the binding is less than zero, or greater than or equal to the |
| * implementation-dependent maximum supported number of units, a |
| * compilation error will occur. When the binding identifier is used |
| * with an array of size N, all elements of the array from binding |
| * through binding + N - 1 must be within this range." |
| */ |
| unsigned limit = ctx->Const.MaxCombinedTextureImageUnits; |
| |
| if (max_index >= limit) { |
| _mesa_glsl_error(loc, state, "layout(binding = %d) for %d samplers " |
| "exceeds the maximum number of texture image units " |
| "(%d)", qual->binding, elements, limit); |
| |
| return false; |
| } |
| } else if (base_type->contains_atomic()) { |
| assert(ctx->Const.MaxAtomicBufferBindings <= MAX_COMBINED_ATOMIC_BUFFERS); |
| if (unsigned(qual->binding) >= ctx->Const.MaxAtomicBufferBindings) { |
| _mesa_glsl_error(loc, state, "layout(binding = %d) exceeds the " |
| " maximum number of atomic counter buffer bindings" |
| "(%d)", qual->binding, |
| ctx->Const.MaxAtomicBufferBindings); |
| |
| return false; |
| } |
| } else if (state->is_version(420, 310) && base_type->is_image()) { |
| assert(ctx->Const.MaxImageUnits <= MAX_IMAGE_UNITS); |
| if (max_index >= ctx->Const.MaxImageUnits) { |
| _mesa_glsl_error(loc, state, "Image binding %d exceeds the " |
| " maximum number of image units (%d)", max_index, |
| ctx->Const.MaxImageUnits); |
| return false; |
| } |
| |
| } else { |
| _mesa_glsl_error(loc, state, |
| "the \"binding\" qualifier only applies to uniform " |
| "blocks, opaque variables, or arrays thereof"); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| |
| static glsl_interp_qualifier |
| interpret_interpolation_qualifier(const struct ast_type_qualifier *qual, |
| ir_variable_mode mode, |
| struct _mesa_glsl_parse_state *state, |
| YYLTYPE *loc) |
| { |
| glsl_interp_qualifier interpolation; |
| if (qual->flags.q.flat) |
| interpolation = INTERP_QUALIFIER_FLAT; |
| else if (qual->flags.q.noperspective) |
| interpolation = INTERP_QUALIFIER_NOPERSPECTIVE; |
| else if (qual->flags.q.smooth) |
| interpolation = INTERP_QUALIFIER_SMOOTH; |
| else |
| interpolation = INTERP_QUALIFIER_NONE; |
| |
| if (interpolation != INTERP_QUALIFIER_NONE) { |
| if (mode != ir_var_shader_in && mode != ir_var_shader_out) { |
| _mesa_glsl_error(loc, state, |
| "interpolation qualifier `%s' can only be applied to " |
| "shader inputs or outputs.", |
| interpolation_string(interpolation)); |
| |
| } |
| |
| if ((state->stage == MESA_SHADER_VERTEX && mode == ir_var_shader_in) || |
| (state->stage == MESA_SHADER_FRAGMENT && mode == ir_var_shader_out)) { |
| _mesa_glsl_error(loc, state, |
| "interpolation qualifier `%s' cannot be applied to " |
| "vertex shader inputs or fragment shader outputs", |
| interpolation_string(interpolation)); |
| } |
| } |
| |
| return interpolation; |
| } |
| |
| |
| static void |
| validate_explicit_location(const struct ast_type_qualifier *qual, |
| ir_variable *var, |
| struct _mesa_glsl_parse_state *state, |
| YYLTYPE *loc) |
| { |
| bool fail = false; |
| |
| /* Checks for GL_ARB_explicit_uniform_location. */ |
| if (qual->flags.q.uniform) { |
| if (!state->check_explicit_uniform_location_allowed(loc, var)) |
| return; |
| |
| const struct gl_context *const ctx = state->ctx; |
| unsigned max_loc = qual->location + var->type->uniform_locations() - 1; |
| |
| /* ARB_explicit_uniform_location specification states: |
| * |
| * "The explicitly defined locations and the generated locations |
| * must be in the range of 0 to MAX_UNIFORM_LOCATIONS minus one." |
| * |
| * "Valid locations for default-block uniform variable locations |
| * are in the range of 0 to the implementation-defined maximum |
| * number of uniform locations." |
| */ |
| if (qual->location < 0) { |
| _mesa_glsl_error(loc, state, |
| "explicit location < 0 for uniform %s", var->name); |
| return; |
| } |
| |
| if (max_loc >= ctx->Const.MaxUserAssignableUniformLocations) { |
| _mesa_glsl_error(loc, state, "location(s) consumed by uniform %s " |
| ">= MAX_UNIFORM_LOCATIONS (%u)", var->name, |
| ctx->Const.MaxUserAssignableUniformLocations); |
| return; |
| } |
| |
| var->data.explicit_location = true; |
| var->data.location = qual->location; |
| return; |
| } |
| |
| /* Between GL_ARB_explicit_attrib_location an |
| * GL_ARB_separate_shader_objects, the inputs and outputs of any shader |
| * stage can be assigned explicit locations. The checking here associates |
| * the correct extension with the correct stage's input / output: |
| * |
| * input output |
| * ----- ------ |
| * vertex explicit_loc sso |
| * tess control sso sso |
| * tess eval sso sso |
| * geometry sso sso |
| * fragment sso explicit_loc |
| */ |
| switch (state->stage) { |
| case MESA_SHADER_VERTEX: |
| if (var->data.mode == ir_var_shader_in) { |
| if (!state->check_explicit_attrib_location_allowed(loc, var)) |
| return; |
| |
| break; |
| } |
| |
| if (var->data.mode == ir_var_shader_out) { |
| if (!state->check_separate_shader_objects_allowed(loc, var)) |
| return; |
| |
| break; |
| } |
| |
| fail = true; |
| break; |
| |
| case MESA_SHADER_TESS_CTRL: |
| case MESA_SHADER_TESS_EVAL: |
| case MESA_SHADER_GEOMETRY: |
| if (var->data.mode == ir_var_shader_in || var->data.mode == ir_var_shader_out) { |
| if (!state->check_separate_shader_objects_allowed(loc, var)) |
| return; |
| |
| break; |
| } |
| |
| fail = true; |
| break; |
| |
| case MESA_SHADER_FRAGMENT: |
| if (var->data.mode == ir_var_shader_in) { |
| if (!state->check_separate_shader_objects_allowed(loc, var)) |
| return; |
| |
| break; |
| } |
| |
| if (var->data.mode == ir_var_shader_out) { |
| if (!state->check_explicit_attrib_location_allowed(loc, var)) |
| return; |
| |
| break; |
| } |
| |
| fail = true; |
| break; |
| |
| case MESA_SHADER_COMPUTE: |
| _mesa_glsl_error(loc, state, |
| "compute shader variables cannot be given " |
| "explicit locations"); |
| return; |
| }; |
| |
| if (fail) { |
| _mesa_glsl_error(loc, state, |
| "%s cannot be given an explicit location in %s shader", |
| mode_string(var), |
| _mesa_shader_stage_to_string(state->stage)); |
| } else { |
| var->data.explicit_location = true; |
| |
| /* This bit of silliness is needed because invalid explicit locations |
| * are supposed to be flagged during linking. Small negative values |
| * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias |
| * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS). |
| * The linker needs to be able to differentiate these cases. This |
| * ensures that negative values stay negative. |
| */ |
| if (qual->location >= 0) { |
| switch (state->stage) { |
| case MESA_SHADER_VERTEX: |
| var->data.location = (var->data.mode == ir_var_shader_in) |
| ? (qual->location + VERT_ATTRIB_GENERIC0) |
| : (qual->location + VARYING_SLOT_VAR0); |
| break; |
| |
| case MESA_SHADER_TESS_CTRL: |
| case MESA_SHADER_TESS_EVAL: |
| case MESA_SHADER_GEOMETRY: |
| if (var->data.patch) |
| var->data.location = qual->location + VARYING_SLOT_PATCH0; |
| else |
| var->data.location = qual->location + VARYING_SLOT_VAR0; |
| break; |
| |
| case MESA_SHADER_FRAGMENT: |
| var->data.location = (var->data.mode == ir_var_shader_out) |
| ? (qual->location + FRAG_RESULT_DATA0) |
| : (qual->location + VARYING_SLOT_VAR0); |
| break; |
| case MESA_SHADER_COMPUTE: |
| assert(!"Unexpected shader type"); |
| break; |
| } |
| } else { |
| var->data.location = qual->location; |
| } |
| |
| if (qual->flags.q.explicit_index) { |
| /* From the GLSL 4.30 specification, section 4.4.2 (Output |
| * Layout Qualifiers): |
| * |
| * "It is also a compile-time error if a fragment shader |
| * sets a layout index to less than 0 or greater than 1." |
| * |
| * Older specifications don't mandate a behavior; we take |
| * this as a clarification and always generate the error. |
| */ |
| if (qual->index < 0 || qual->index > 1) { |
| _mesa_glsl_error(loc, state, |
| "explicit index may only be 0 or 1"); |
| } else { |
| var->data.explicit_index = true; |
| var->data.index = qual->index; |
| } |
| } |
| } |
| } |
| |
| static void |
| apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual, |
| ir_variable *var, |
| struct _mesa_glsl_parse_state *state, |
| YYLTYPE *loc) |
| { |
| const glsl_type *base_type = var->type->without_array(); |
| |
| if (base_type->is_image()) { |
| if (var->data.mode != ir_var_uniform && |
| var->data.mode != ir_var_function_in) { |
| _mesa_glsl_error(loc, state, "image variables may only be declared as " |
| "function parameters or uniform-qualified " |
| "global variables"); |
| } |
| |
| var->data.image_read_only |= qual->flags.q.read_only; |
| var->data.image_write_only |= qual->flags.q.write_only; |
| var->data.image_coherent |= qual->flags.q.coherent; |
| var->data.image_volatile |= qual->flags.q._volatile; |
| var->data.image_restrict |= qual->flags.q.restrict_flag; |
| var->data.read_only = true; |
| |
| if (qual->flags.q.explicit_image_format) { |
| if (var->data.mode == ir_var_function_in) { |
| _mesa_glsl_error(loc, state, "format qualifiers cannot be " |
| "used on image function parameters"); |
| } |
| |
| if (qual->image_base_type != base_type->sampler_type) { |
| _mesa_glsl_error(loc, state, "format qualifier doesn't match the " |
| "base data type of the image"); |
| } |
| |
| var->data.image_format = qual->image_format; |
| } else { |
| if (var->data.mode == ir_var_uniform) { |
| if (state->es_shader) { |
| _mesa_glsl_error(loc, state, "all image uniforms " |
| "must have a format layout qualifier"); |
| |
| } else if (!qual->flags.q.write_only) { |
| _mesa_glsl_error(loc, state, "image uniforms not qualified with " |
| "`writeonly' must have a format layout " |
| "qualifier"); |
| } |
| } |
| |
| var->data.image_format = GL_NONE; |
| } |
| |
| /* From page 70 of the GLSL ES 3.1 specification: |
| * |
| * "Except for image variables qualified with the format qualifiers |
| * r32f, r32i, and r32ui, image variables must specify either memory |
| * qualifier readonly or the memory qualifier writeonly." |
| */ |
| if (state->es_shader && |
| var->data.image_format != GL_R32F && |
| var->data.image_format != GL_R32I && |
| var->data.image_format != GL_R32UI && |
| !var->data.image_read_only && |
| !var->data.image_write_only) { |
| _mesa_glsl_error(loc, state, "image variables of format other than " |
| "r32f, r32i or r32ui must be qualified `readonly' or " |
| "`writeonly'"); |
| } |
| |
| } else if (qual->flags.q.read_only || |
| qual->flags.q.write_only || |
| qual->flags.q.coherent || |
| qual->flags.q._volatile || |
| qual->flags.q.restrict_flag || |
| qual->flags.q.explicit_image_format) { |
| _mesa_glsl_error(loc, state, "memory qualifiers may only be applied to " |
| "images"); |
| } |
| } |
| |
| static inline const char* |
| get_layout_qualifier_string(bool origin_upper_left, bool pixel_center_integer) |
| { |
| if (origin_upper_left && pixel_center_integer) |
| return "origin_upper_left, pixel_center_integer"; |
| else if (origin_upper_left) |
| return "origin_upper_left"; |
| else if (pixel_center_integer) |
| return "pixel_center_integer"; |
| else |
| return " "; |
| } |
| |
| static inline bool |
| is_conflicting_fragcoord_redeclaration(struct _mesa_glsl_parse_state *state, |
| const struct ast_type_qualifier *qual) |
| { |
| /* If gl_FragCoord was previously declared, and the qualifiers were |
| * different in any way, return true. |
| */ |
| if (state->fs_redeclares_gl_fragcoord) { |
| return (state->fs_pixel_center_integer != qual->flags.q.pixel_center_integer |
| || state->fs_origin_upper_left != qual->flags.q.origin_upper_left); |
| } |
| |
| return false; |
| } |
| |
| static void |
| apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, |
| ir_variable *var, |
| struct _mesa_glsl_parse_state *state, |
| YYLTYPE *loc, |
| bool is_parameter) |
| { |
| STATIC_ASSERT(sizeof(qual->flags.q) <= sizeof(qual->flags.i)); |
| |
| if (qual->flags.q.invariant) { |
| if (var->data.used) { |
| _mesa_glsl_error(loc, state, |
| "variable `%s' may not be redeclared " |
| "`invariant' after being used", |
| var->name); |
| } else { |
| var->data.invariant = 1; |
| } |
| } |
| |
| if (qual->flags.q.precise) { |
| if (var->data.used) { |
| _mesa_glsl_error(loc, state, |
| "variable `%s' may not be redeclared " |
| "`precise' after being used", |
| var->name); |
| } else { |
| var->data.precise = 1; |
| } |
| } |
| |
| if (qual->flags.q.subroutine && !qual->flags.q.uniform) { |
| _mesa_glsl_error(loc, state, |
| "`subroutine' may only be applied to uniforms, " |
| "subroutine type declarations, or function definitions"); |
| } |
| |
| if (qual->flags.q.constant || qual->flags.q.attribute |
| || qual->flags.q.uniform |
| || (qual->flags.q.varying && (state->stage == MESA_SHADER_FRAGMENT))) |
| var->data.read_only = 1; |
| |
| if (qual->flags.q.centroid) |
| var->data.centroid = 1; |
| |
| if (qual->flags.q.sample) |
| var->data.sample = 1; |
| |
| if (state->stage == MESA_SHADER_GEOMETRY && |
| qual->flags.q.out && qual->flags.q.stream) { |
| var->data.stream = qual->stream; |
| } |
| |
| if (qual->flags.q.patch) |
| var->data.patch = 1; |
| |
| if (qual->flags.q.attribute && state->stage != MESA_SHADER_VERTEX) { |
| var->type = glsl_type::error_type; |
| _mesa_glsl_error(loc, state, |
| "`attribute' variables may not be declared in the " |
| "%s shader", |
| _mesa_shader_stage_to_string(state->stage)); |
| } |
| |
| /* Disallow layout qualifiers which may only appear on layout declarations. */ |
| if (qual->flags.q.prim_type) { |
| _mesa_glsl_error(loc, state, |
| "Primitive type may only be specified on GS input or output " |
| "layout declaration, not on variables."); |
| } |
| |
| /* Section 6.1.1 (Function Calling Conventions) of the GLSL 1.10 spec says: |
| * |
| * "However, the const qualifier cannot be used with out or inout." |
| * |
| * The same section of the GLSL 4.40 spec further clarifies this saying: |
| * |
| * "The const qualifier cannot be used with out or inout, or a |
| * compile-time error results." |
| */ |
| if (is_parameter && qual->flags.q.constant && qual->flags.q.out) { |
| _mesa_glsl_error(loc, state, |
| "`const' may not be applied to `out' or `inout' " |
| "function parameters"); |
| } |
| |
| /* If there is no qualifier that changes the mode of the variable, leave |
| * the setting alone. |
| */ |
| assert(var->data.mode != ir_var_temporary); |
| if (qual->flags.q.in && qual->flags.q.out) |
| var->data.mode = ir_var_function_inout; |
| else if (qual->flags.q.in) |
| var->data.mode = is_parameter ? ir_var_function_in : ir_var_shader_in; |
| else if (qual->flags.q.attribute |
| || (qual->flags.q.varying && (state->stage == MESA_SHADER_FRAGMENT))) |
| var->data.mode = ir_var_shader_in; |
| else if (qual->flags.q.out) |
| var->data.mode = is_parameter ? ir_var_function_out : ir_var_shader_out; |
| else if (qual->flags.q.varying && (state->stage == MESA_SHADER_VERTEX)) |
| var->data.mode = ir_var_shader_out; |
| else if (qual->flags.q.uniform) |
| var->data.mode = ir_var_uniform; |
| else if (qual->flags.q.buffer) |
| var->data.mode = ir_var_shader_storage; |
| |
| if (!is_parameter && is_varying_var(var, state->stage)) { |
| /* User-defined ins/outs are not permitted in compute shaders. */ |
| if (state->stage == MESA_SHADER_COMPUTE) { |
| _mesa_glsl_error(loc, state, |
| "user-defined input and output variables are not " |
| "permitted in compute shaders"); |
| } |
| |
| /* This variable is being used to link data between shader stages (in |
| * pre-glsl-1.30 parlance, it's a "varying"). Check that it has a type |
| * that is allowed for such purposes. |
| * |
| * From page 25 (page 31 of the PDF) of the GLSL 1.10 spec: |
| * |
| * "The varying qualifier can be used only with the data types |
| * float, vec2, vec3, vec4, mat2, mat3, and mat4, or arrays of |
| * these." |
| * |
| * This was relaxed in GLSL version 1.30 and GLSL ES version 3.00. From |
| * page 31 (page 37 of the PDF) of the GLSL 1.30 spec: |
| * |
| * "Fragment inputs can only be signed and unsigned integers and |
| * integer vectors, float, floating-point vectors, matrices, or |
| * arrays of these. Structures cannot be input. |
| * |
| * Similar text exists in the section on vertex shader outputs. |
| * |
| * Similar text exists in the GLSL ES 3.00 spec, except that the GLSL ES |
| * 3.00 spec allows structs as well. Varying structs are also allowed |
| * in GLSL 1.50. |
| */ |
| switch (var->type->get_scalar_type()->base_type) { |
| case GLSL_TYPE_FLOAT: |
| /* Ok in all GLSL versions */ |
| break; |
| case GLSL_TYPE_UINT: |
| case GLSL_TYPE_INT: |
| if (state->is_version(130, 300)) |
| break; |
| _mesa_glsl_error(loc, state, |
| "varying variables must be of base type float in %s", |
| state->get_version_string()); |
| break; |
| case GLSL_TYPE_STRUCT: |
| if (state->is_version(150, 300)) |
| break; |
| _mesa_glsl_error(loc, state, |
| "varying variables may not be of type struct"); |
| break; |
| case GLSL_TYPE_DOUBLE: |
| break; |
| default: |
| _mesa_glsl_error(loc, state, "illegal type for a varying variable"); |
| break; |
| } |
| } |
| |
| if (state->all_invariant && (state->current_function == NULL)) { |
| switch (state->stage) { |
| case MESA_SHADER_VERTEX: |
| if (var->data.mode == ir_var_shader_out) |
| var->data.invariant = true; |
| break; |
| case MESA_SHADER_TESS_CTRL: |
| case MESA_SHADER_TESS_EVAL: |
| case MESA_SHADER_GEOMETRY: |
| if ((var->data.mode == ir_var_shader_in) |
| || (var->data.mode == ir_var_shader_out)) |
| var->data.invariant = true; |
| break; |
| case MESA_SHADER_FRAGMENT: |
| if (var->data.mode == ir_var_shader_in) |
| var->data.invariant = true; |
| break; |
| case MESA_SHADER_COMPUTE: |
| /* Invariance isn't meaningful in compute shaders. */ |
| break; |
| } |
| } |
| |
| var->data.interpolation = |
| interpret_interpolation_qualifier(qual, (ir_variable_mode) var->data.mode, |
| state, loc); |
| |
| var->data.pixel_center_integer = qual->flags.q.pixel_center_integer; |
| var->data.origin_upper_left = qual->flags.q.origin_upper_left; |
| if ((qual->flags.q.origin_upper_left || qual->flags.q.pixel_center_integer) |
| && (strcmp(var->name, "gl_FragCoord") != 0)) { |
| const char *const qual_string = (qual->flags.q.origin_upper_left) |
| ? "origin_upper_left" : "pixel_center_integer"; |
| |
| _mesa_glsl_error(loc, state, |
| "layout qualifier `%s' can only be applied to " |
| "fragment shader input `gl_FragCoord'", |
| qual_string); |
| } |
| |
| if (var->name != NULL && strcmp(var->name, "gl_FragCoord") == 0) { |
| |
| /* Section 4.3.8.1, page 39 of GLSL 1.50 spec says: |
| * |
| * "Within any shader, the first redeclarations of gl_FragCoord |
| * must appear before any use of gl_FragCoord." |
| * |
| * Generate a compiler error if above condition is not met by the |
| * fragment shader. |
| */ |
| ir_variable *earlier = state->symbols->get_variable("gl_FragCoord"); |
| if (earlier != NULL && |
| earlier->data.used && |
| !state->fs_redeclares_gl_fragcoord) { |
| _mesa_glsl_error(loc, state, |
| "gl_FragCoord used before its first redeclaration " |
| "in fragment shader"); |
| } |
| |
| /* Make sure all gl_FragCoord redeclarations specify the same layout |
| * qualifiers. |
| */ |
| if (is_conflicting_fragcoord_redeclaration(state, qual)) { |
| const char *const qual_string = |
| get_layout_qualifier_string(qual->flags.q.origin_upper_left, |
| qual->flags.q.pixel_center_integer); |
| |
| const char *const state_string = |
| get_layout_qualifier_string(state->fs_origin_upper_left, |
| state->fs_pixel_center_integer); |
| |
| _mesa_glsl_error(loc, state, |
| "gl_FragCoord redeclared with different layout " |
| "qualifiers (%s) and (%s) ", |
| state_string, |
| qual_string); |
| } |
| state->fs_origin_upper_left = qual->flags.q.origin_upper_left; |
| state->fs_pixel_center_integer = qual->flags.q.pixel_center_integer; |
| state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers = |
| !qual->flags.q.origin_upper_left && !qual->flags.q.pixel_center_integer; |
| state->fs_redeclares_gl_fragcoord = |
| state->fs_origin_upper_left || |
| state->fs_pixel_center_integer || |
| state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers; |
| } |
| |
| if (qual->flags.q.explicit_location) { |
| validate_explicit_location(qual, var, state, loc); |
| } else if (qual->flags.q.explicit_index) { |
| _mesa_glsl_error(loc, state, "explicit index requires explicit location"); |
| } |
| |
| if (qual->flags.q.explicit_binding && |
| validate_binding_qualifier(state, loc, var->type, qual)) { |
| var->data.explicit_binding = true; |
| var->data.binding = qual->binding; |
| } |
| |
| if (var->type->contains_atomic()) { |
| if (var->data.mode == ir_var_uniform) { |
| if (var->data.explicit_binding) { |
| unsigned *offset = |
| &state->atomic_counter_offsets[var->data.binding]; |
| |
| if (*offset % ATOMIC_COUNTER_SIZE) |
| _mesa_glsl_error(loc, state, |
| "misaligned atomic counter offset"); |
| |
| var->data.atomic.offset = *offset; |
| *offset += var->type->atomic_size(); |
| |
| } else { |
| _mesa_glsl_error(loc, state, |
| "atomic counters require explicit binding point"); |
| } |
| } else if (var->data.mode != ir_var_function_in) { |
| _mesa_glsl_error(loc, state, "atomic counters may only be declared as " |
| "function parameters or uniform-qualified " |
| "global variables"); |
| } |
| } |
| |
| /* Does the declaration use the deprecated 'attribute' or 'varying' |
| * keywords? |
| */ |
| const bool uses_deprecated_qualifier = qual->flags.q.attribute |
| || qual->flags.q.varying; |
| |
| |
| /* Validate auxiliary storage qualifiers */ |
| |
| /* From section 4.3.4 of the GLSL 1.30 spec: |
| * "It is an error to use centroid in in a vertex shader." |
| * |
| * From section 4.3.4 of the GLSL ES 3.00 spec: |
| * "It is an error to use centroid in or interpolation qualifiers in |
| * a vertex shader input." |
| */ |
| |
| /* Section 4.3.6 of the GLSL 1.30 specification states: |
| * "It is an error to use centroid out in a fragment shader." |
| * |
| * The GL_ARB_shading_language_420pack extension specification states: |
| * "It is an error to use auxiliary storage qualifiers or interpolation |
| * qualifiers on an output in a fragment shader." |
| */ |
| if (qual->flags.q.sample && (!is_varying_var(var, state->stage) || uses_deprecated_qualifier)) { |
| _mesa_glsl_error(loc, state, |
| "sample qualifier may only be used on `in` or `out` " |
| "variables between shader stages"); |
| } |
| if (qual->flags.q.centroid && !is_varying_var(var, state->stage)) { |
| _mesa_glsl_error(loc, state, |
| "centroid qualifier may only be used with `in', " |
| "`out' or `varying' variables between shader stages"); |
| } |
| |
| |
| /* Is the 'layout' keyword used with parameters that allow relaxed checking. |
| * Many implementations of GL_ARB_fragment_coord_conventions_enable and some |
| * implementations (only Mesa?) GL_ARB_explicit_attrib_location_enable |
| * allowed the layout qualifier to be used with 'varying' and 'attribute'. |
| * These extensions and all following extensions that add the 'layout' |
| * keyword have been modified to require the use of 'in' or 'out'. |
| * |
| * The following extension do not allow the deprecated keywords: |
| * |
| * GL_AMD_conservative_depth |
| * GL_ARB_conservative_depth |
| * GL_ARB_gpu_shader5 |
| * GL_ARB_separate_shader_objects |
| * GL_ARB_tessellation_shader |
| * GL_ARB_transform_feedback3 |
| * GL_ARB_uniform_buffer_object |
| * |
| * It is unknown whether GL_EXT_shader_image_load_store or GL_NV_gpu_shader5 |
| * allow layout with the deprecated keywords. |
| */ |
| const bool relaxed_layout_qualifier_checking = |
| state->ARB_fragment_coord_conventions_enable; |
| |
| if (qual->has_layout() && uses_deprecated_qualifier) { |
| if (relaxed_layout_qualifier_checking) { |
| _mesa_glsl_warning(loc, state, |
| "`layout' qualifier may not be used with " |
| "`attribute' or `varying'"); |
| } else { |
| _mesa_glsl_error(loc, state, |
| "`layout' qualifier may not be used with " |
| "`attribute' or `varying'"); |
| } |
| } |
| |
| /* 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 |
| && !state->ARB_conservative_depth_enable) { |
| _mesa_glsl_error(loc, state, |
| "extension GL_AMD_conservative_depth or " |
| "GL_ARB_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->data.depth_layout = ir_depth_layout_any; |
| else if (qual->flags.q.depth_greater) |
| var->data.depth_layout = ir_depth_layout_greater; |
| else if (qual->flags.q.depth_less) |
| var->data.depth_layout = ir_depth_layout_less; |
| else if (qual->flags.q.depth_unchanged) |
| var->data.depth_layout = ir_depth_layout_unchanged; |
| else |
| var->data.depth_layout = ir_depth_layout_none; |
| |
| if (qual->flags.q.std140 || |
| qual->flags.q.std430 || |
| qual->flags.q.packed || |
| qual->flags.q.shared) { |
| _mesa_glsl_error(loc, state, |
| "uniform and shader storage block layout qualifiers " |
| "std140, std430, packed, and shared can only be " |
| "applied to uniform or shader storage blocks, not " |
| "members"); |
| } |
| |
| if (qual->flags.q.row_major || qual->flags.q.column_major) { |
| validate_matrix_layout_for_type(state, loc, var->type, var); |
| } |
| |
| apply_image_qualifier_to_variable(qual, var, state, loc); |
| |
| /* From section 4.4.1.3 of the GLSL 4.50 specification (Fragment Shader |
| * Inputs): |
| * |
| * "Fragment shaders also allow the following layout qualifier on in only |
| * (not with variable declarations) |
| * layout-qualifier-id |
| * early_fragment_tests |
| * [...]" |
| */ |
| if (qual->flags.q.early_fragment_tests) { |
| _mesa_glsl_error(loc, state, "early_fragment_tests layout qualifier only " |
| "valid in fragment shader input layout declaration."); |
| } |
| } |
| |
| /** |
| * Get the variable that is being redeclared by this declaration |
| * |
| * Semantic checks to verify the validity of the redeclaration are also |
| * performed. If semantic checks fail, compilation error will be emitted via |
| * \c _mesa_glsl_error, but a non-\c NULL pointer will still be returned. |
| * |
| * \returns |
| * A pointer to an existing variable in the current scope if the declaration |
| * is a redeclaration, \c NULL otherwise. |
| */ |
| static ir_variable * |
| get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, |
| struct _mesa_glsl_parse_state *state, |
| bool allow_all_redeclarations) |
| { |
| /* Check if this declaration is actually a re-declaration, either to |
| * resize an array or add qualifiers to an existing variable. |
| * |
| * This is allowed for variables in the current scope, or when at |
| * global scope (for built-ins in the implicit outer scope). |
| */ |
| ir_variable *earlier = state->symbols->get_variable(var->name); |
| if (earlier == NULL || |
| (state->current_function != NULL && |
| !state->symbols->name_declared_this_scope(var->name))) { |
| return NULL; |
| } |
| |
| |
| /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec, |
| * |
| * "It is legal to declare an array without a size and then |
| * later re-declare the same name as an array of the same |
| * type and specify a size." |
| */ |
| if (earlier->type->is_unsized_array() && var->type->is_array() |
| && (var->type->fields.array == earlier->type->fields.array)) { |
| /* FINISHME: This doesn't match the qualifiers on the two |
| * FINISHME: declarations. It's not 100% clear whether this is |
| * FINISHME: required or not. |
| */ |
| |
| const unsigned size = unsigned(var->type->array_size()); |
| check_builtin_array_max_size(var->name, size, loc, state); |
| if ((size > 0) && (size <= earlier->data.max_array_access)) { |
| _mesa_glsl_error(& loc, state, "array size must be > %u due to " |
| "previous access", |
| earlier->data.max_array_access); |
| } |
| |
| earlier->type = var->type; |
| delete var; |
| var = NULL; |
| } else if ((state->ARB_fragment_coord_conventions_enable || |
| state->is_version(150, 0)) |
| && strcmp(var->name, "gl_FragCoord") == 0 |
| && earlier->type == var->type |
| && earlier->data.mode == var->data.mode) { |
| /* Allow redeclaration of gl_FragCoord for ARB_fcc layout |
| * qualifiers. |
| */ |
| earlier->data.origin_upper_left = var->data.origin_upper_left; |
| earlier->data.pixel_center_integer = var->data.pixel_center_integer; |
| |
| /* According to section 4.3.7 of the GLSL 1.30 spec, |
| * the following built-in varaibles can be redeclared with an |
| * interpolation qualifier: |
| * * gl_FrontColor |
| * * gl_BackColor |
| * * gl_FrontSecondaryColor |
| * * gl_BackSecondaryColor |
| * * gl_Color |
| * * gl_SecondaryColor |
| */ |
| } else if (state->is_version(130, 0) |
| && (strcmp(var->name, "gl_FrontColor") == 0 |
| || strcmp(var->name, "gl_BackColor") == 0 |
| || strcmp(var->name, "gl_FrontSecondaryColor") == 0 |
| || strcmp(var->name, "gl_BackSecondaryColor") == 0 |
| || strcmp(var->name, "gl_Color") == 0 |
| || strcmp(var->name, "gl_SecondaryColor") == 0) |
| && earlier->type == var->type |
| && earlier->data.mode == var->data.mode) { |
| earlier->data.interpolation = var->data.interpolation; |
| |
| /* Layout qualifiers for gl_FragDepth. */ |
| } else if ((state->AMD_conservative_depth_enable || |
| state->ARB_conservative_depth_enable) |
| && strcmp(var->name, "gl_FragDepth") == 0 |
| && earlier->type == var->type |
| && earlier->data.mode == var->data.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->data.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->data.depth_layout != ir_depth_layout_none |
| && earlier->data.depth_layout != var->data.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->data.depth_layout), |
| depth_layout_string(earlier->data.depth_layout)); |
| } |
| |
| earlier->data.depth_layout = var->data.depth_layout; |
| |
| } else if (allow_all_redeclarations) { |
| if (earlier->data.mode != var->data.mode) { |
| _mesa_glsl_error(&loc, state, |
| "redeclaration of `%s' with incorrect qualifiers", |
| var->name); |
| } else if (earlier->type != var->type) { |
| _mesa_glsl_error(&loc, state, |
| "redeclaration of `%s' has incorrect type", |
| var->name); |
| } |
| } else { |
| _mesa_glsl_error(&loc, state, "`%s' redeclared", var->name); |
| } |
| |
| return earlier; |
| } |
| |
| /** |
| * Generate the IR for an initializer in a variable declaration |
| */ |
| ir_rvalue * |
| process_initializer(ir_variable *var, ast_declaration *decl, |
| ast_fully_specified_type *type, |
| exec_list *initializer_instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| ir_rvalue *result = NULL; |
| |
| YYLTYPE initializer_loc = decl->initializer->get_location(); |
| |
| /* From page 24 (page 30 of the PDF) of the GLSL 1.10 spec: |
| * |
| * "All uniform variables are read-only and are initialized either |
| * directly by an application via API commands, or indirectly by |
| * OpenGL." |
| */ |
| if (var->data.mode == ir_var_uniform) { |
| state->check_version(120, 0, &initializer_loc, |
| "cannot initialize uniforms"); |
| } |
| |
| /* Section 4.3.7 "Buffer Variables" of the GLSL 4.30 spec: |
| * |
| * "Buffer variables cannot have initializers." |
| */ |
| if (var->data.mode == ir_var_shader_storage) { |
| _mesa_glsl_error(& initializer_loc, state, |
| "SSBO variables cannot have initializers"); |
| } |
| |
| /* From section 4.1.7 of the GLSL 4.40 spec: |
| * |
| * "Opaque variables [...] are initialized only through the |
| * OpenGL API; they cannot be declared with an initializer in a |
| * shader." |
| */ |
| if (var->type->contains_opaque()) { |
| _mesa_glsl_error(& initializer_loc, state, |
| "cannot initialize opaque variable"); |
| } |
| |
| if ((var->data.mode == ir_var_shader_in) && (state->current_function == NULL)) { |
| _mesa_glsl_error(& initializer_loc, state, |
| "cannot initialize %s shader input / %s", |
| _mesa_shader_stage_to_string(state->stage), |
| (state->stage == MESA_SHADER_VERTEX) |
| ? "attribute" : "varying"); |
| } |
| |
| /* If the initializer is an ast_aggregate_initializer, recursively store |
| * type information from the LHS into it, so that its hir() function can do |
| * type checking. |
| */ |
| if (decl->initializer->oper == ast_aggregate) |
| _mesa_ast_set_aggregate_type(var->type, decl->initializer); |
| |
| ir_dereference *const lhs = new(state) ir_dereference_variable(var); |
| ir_rvalue *rhs = decl->initializer->hir(initializer_instructions, state); |
| |
| /* Calculate the constant value if this is a const or uniform |
| * declaration. |
| */ |
| if (type->qualifier.flags.q.constant |
| || type->qualifier.flags.q.uniform) { |
| ir_rvalue *new_rhs = validate_assignment(state, initializer_loc, |
| lhs, rhs, true); |
| if (new_rhs != NULL) { |
| rhs = new_rhs; |
| |
| ir_constant *constant_value = rhs->constant_expression_value(); |
| if (!constant_value) { |
| /* If ARB_shading_language_420pack is enabled, initializers of |
| * const-qualified local variables do not have to be constant |
| * expressions. Const-qualified global variables must still be |
| * initialized with constant expressions. |
| */ |
| if (!state->ARB_shading_language_420pack_enable |
| || state->current_function == NULL) { |
| _mesa_glsl_error(& initializer_loc, state, |
| "initializer of %s variable `%s' must be a " |
| "constant expression", |
| (type->qualifier.flags.q.constant) |
| ? "const" : "uniform", |
| decl->identifier); |
| if (var->type->is_numeric()) { |
| /* Reduce cascading errors. */ |
| var->constant_value = ir_constant::zero(state, var->type); |
| } |
| } |
| } else { |
| rhs = constant_value; |
| var->constant_value = constant_value; |
| } |
| } else { |
| if (var->type->is_numeric()) { |
| /* Reduce cascading errors. */ |
| var->constant_value = ir_constant::zero(state, var->type); |
| } |
| } |
| } |
| |
| if (rhs && !rhs->type->is_error()) { |
| bool temp = var->data.read_only; |
| if (type->qualifier.flags.q.constant) |
| var->data.read_only = false; |
| |
| /* Never emit code to initialize a uniform. |
| */ |
| const glsl_type *initializer_type; |
| if (!type->qualifier.flags.q.uniform) { |
| do_assignment(initializer_instructions, state, |
| NULL, |
| lhs, rhs, |
| &result, true, |
| true, |
| type->get_location()); |
| initializer_type = result->type; |
| } else |
| initializer_type = rhs->type; |
| |
| var->constant_initializer = rhs->constant_expression_value(); |
| var->data.has_initializer = true; |
| |
| /* If the declared variable is an unsized array, it must inherrit |
| * its full type from the initializer. A declaration such as |
| * |
| * uniform float a[] = float[](1.0, 2.0, 3.0, 3.0); |
| * |
| * becomes |
| * |
| * uniform float a[4] = float[](1.0, 2.0, 3.0, 3.0); |
| * |
| * The assignment generated in the if-statement (below) will also |
| * automatically handle this case for non-uniforms. |
| * |
| * If the declared variable is not an array, the types must |
| * already match exactly. As a result, the type assignment |
| * here can be done unconditionally. For non-uniforms the call |
| * to do_assignment can change the type of the initializer (via |
| * the implicit conversion rules). For uniforms the initializer |
| * must be a constant expression, and the type of that expression |
| * was validated above. |
| */ |
| var->type = initializer_type; |
| |
| var->data.read_only = temp; |
| } |
| |
| return result; |
| } |
| |
| static void |
| validate_layout_qualifier_vertex_count(struct _mesa_glsl_parse_state *state, |
| YYLTYPE loc, ir_variable *var, |
| unsigned num_vertices, |
| unsigned *size, |
| const char *var_category) |
| { |
| if (var->type->is_unsized_array()) { |
| /* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec says: |
| * |
| * All geometry shader input unsized array declarations will be |
| * sized by an earlier input layout qualifier, when present, as per |
| * the following table. |
| * |
| * Followed by a table mapping each allowed input layout qualifier to |
| * the corresponding input length. |
| * |
| * Similarly for tessellation control shader outputs. |
| */ |
| if (num_vertices != 0) |
| var->type = glsl_type::get_array_instance(var->type->fields.array, |
| num_vertices); |
| } else { |
| /* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec |
| * includes the following examples of compile-time errors: |
| * |
| * // code sequence within one shader... |
| * in vec4 Color1[]; // size unknown |
| * ...Color1.length()...// illegal, length() unknown |
| * in vec4 Color2[2]; // size is 2 |
| * ...Color1.length()...// illegal, Color1 still has no size |
| * in vec4 Color3[3]; // illegal, input sizes are inconsistent |
| * layout(lines) in; // legal, input size is 2, matching |
| * in vec4 Color4[3]; // illegal, contradicts layout |
| * ... |
| * |
| * To detect the case illustrated by Color3, we verify that the size of |
| * an explicitly-sized array matches the size of any previously declared |
| * explicitly-sized array. To detect the case illustrated by Color4, we |
| * verify that the size of an explicitly-sized array is consistent with |
| * any previously declared input layout. |
| */ |
| if (num_vertices != 0 && var->type->length != num_vertices) { |
| _mesa_glsl_error(&loc, state, |
| "%s size contradicts previously declared layout " |
| "(size is %u, but layout requires a size of %u)", |
| var_category, var->type->length, num_vertices); |
| } else if (*size != 0 && var->type->length != *size) { |
| _mesa_glsl_error(&loc, state, |
| "%s sizes are inconsistent (size is %u, but a " |
| "previous declaration has size %u)", |
| var_category, var->type->length, *size); |
| } else { |
| *size = var->type->length; |
| } |
| } |
| } |
| |
| static void |
| handle_tess_ctrl_shader_output_decl(struct _mesa_glsl_parse_state *state, |
| YYLTYPE loc, ir_variable *var) |
| { |
| unsigned num_vertices = 0; |
| |
| if (state->tcs_output_vertices_specified) { |
| num_vertices = state->out_qualifier->vertices; |
| } |
| |
| if (!var->type->is_array() && !var->data.patch) { |
| _mesa_glsl_error(&loc, state, |
| "tessellation control shader outputs must be arrays"); |
| |
| /* To avoid cascading failures, short circuit the checks below. */ |
| return; |
| } |
| |
| if (var->data.patch) |
| return; |
| |
| validate_layout_qualifier_vertex_count(state, loc, var, num_vertices, |
| &state->tcs_output_size, |
| "tessellation control shader output"); |
| } |
| |
| /** |
| * Do additional processing necessary for tessellation control/evaluation shader |
| * input declarations. This covers both interface block arrays and bare input |
| * variables. |
| */ |
| static void |
| handle_tess_shader_input_decl(struct _mesa_glsl_parse_state *state, |
| YYLTYPE loc, ir_variable *var) |
| { |
| if (!var->type->is_array() && !var->data.patch) { |
| _mesa_glsl_error(&loc, state, |
| "per-vertex tessellation shader inputs must be arrays"); |
| /* Avoid cascading failures. */ |
| return; |
| } |
| |
| if (var->data.patch) |
| return; |
| |
| /* Unsized arrays are implicitly sized to gl_MaxPatchVertices. */ |
| if (var->type->is_unsized_array()) { |
| var->type = glsl_type::get_array_instance(var->type->fields.array, |
| state->Const.MaxPatchVertices); |
| } |
| } |
| |
| |
| /** |
| * Do additional processing necessary for geometry shader input declarations |
| * (this covers both interface blocks arrays and bare input variables). |
| */ |
| static void |
| handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state, |
| YYLTYPE loc, ir_variable *var) |
| { |
| unsigned num_vertices = 0; |
| |
| if (state->gs_input_prim_type_specified) { |
| num_vertices = vertices_per_prim(state->in_qualifier->prim_type); |
| } |
| |
| /* Geometry shader input variables must be arrays. Caller should have |
| * reported an error for this. |
| */ |
| if (!var->type->is_array()) { |
| assert(state->error); |
| |
| /* To avoid cascading failures, short circuit the checks below. */ |
| return; |
| } |
| |
| validate_layout_qualifier_vertex_count(state, loc, var, num_vertices, |
| &state->gs_input_size, |
| "geometry shader input"); |
| } |
| |
| void |
| validate_identifier(const char *identifier, YYLTYPE loc, |
| struct _mesa_glsl_parse_state *state) |
| { |
| /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec, |
| * |
| * "Identifiers starting with "gl_" are reserved for use by |
| * OpenGL, and may not be declared in a shader as either a |
| * variable or a function." |
| */ |
| if (is_gl_identifier(identifier)) { |
| _mesa_glsl_error(&loc, state, |
| "identifier `%s' uses reserved `gl_' prefix", |
| identifier); |
| } else if (strstr(identifier, "__")) { |
| /* From page 14 (page 20 of the PDF) of the GLSL 1.10 |
| * spec: |
| * |
| * "In addition, all identifiers containing two |
| * consecutive underscores (__) are reserved as |
| * possible future keywords." |
| * |
| * The intention is that names containing __ are reserved for internal |
| * use by the implementation, and names prefixed with GL_ are reserved |
| * for use by Khronos. Names simply containing __ are dangerous to use, |
| * but should be allowed. |
| * |
| * A future version of the GLSL specification will clarify this. |
| */ |
| _mesa_glsl_warning(&loc, state, |
| "identifier `%s' uses reserved `__' string", |
| identifier); |
| } |
| } |
| |
| static bool |
| precision_qualifier_allowed(const glsl_type *type) |
| { |
| /* Precision qualifiers apply to floating point, integer and opaque |
| * types. |
| * |
| * Section 4.5.2 (Precision Qualifiers) of the GLSL 1.30 spec says: |
| * "Any floating point or any integer declaration can have the type |
| * preceded by one of these precision qualifiers [...] Literal |
| * constants do not have precision qualifiers. Neither do Boolean |
| * variables. |
| * |
| * Section 4.5 (Precision and Precision Qualifiers) of the GLSL 1.30 |
| * spec also says: |
| * |
| * "Precision qualifiers are added for code portability with OpenGL |
| * ES, not for functionality. They have the same syntax as in OpenGL |
| * ES." |
| * |
| * Section 8 (Built-In Functions) of the GLSL ES 1.00 spec says: |
| * |
| * "uniform lowp sampler2D sampler; |
| * highp vec2 coord; |
| * ... |
| * lowp vec4 col = texture2D (sampler, coord); |
| * // texture2D returns lowp" |
| * |
| * From this, we infer that GLSL 1.30 (and later) should allow precision |
| * qualifiers on sampler types just like float and integer types. |
| */ |
| return type->is_float() |
| || type->is_integer() |
| || type->is_record() |
| || type->contains_opaque(); |
| } |
| |
| ir_rvalue * |
| ast_declarator_list::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| void *ctx = state; |
| const struct glsl_type *decl_type; |
| const char *type_name = NULL; |
| ir_rvalue *result = NULL; |
| YYLTYPE loc = this->get_location(); |
| |
| /* From page 46 (page 52 of the PDF) of the GLSL 1.50 spec: |
| * |
| * "To ensure that a particular output variable is invariant, it is |
| * necessary to use the invariant qualifier. It can either be used to |
| * qualify a previously declared variable as being invariant |
| * |
| * invariant gl_Position; // make existing gl_Position be invariant" |
| * |
| * In these cases the parser will set the 'invariant' flag in the declarator |
| * list, and the type will be NULL. |
| */ |
| if (this->invariant) { |
| assert(this->type == NULL); |
| |
| if (state->current_function != NULL) { |
| _mesa_glsl_error(& loc, state, |
| "all uses of `invariant' keyword must be at global " |
| "scope"); |
| } |
| |
| foreach_list_typed (ast_declaration, decl, link, &this->declarations) { |
| assert(decl->array_specifier == NULL); |
| assert(decl->initializer == NULL); |
| |
| ir_variable *const earlier = |
| state->symbols->get_variable(decl->identifier); |
| if (earlier == NULL) { |
| _mesa_glsl_error(& loc, state, |
| "undeclared variable `%s' cannot be marked " |
| "invariant", decl->identifier); |
| } else if (!is_varying_var(earlier, state->stage)) { |
| _mesa_glsl_error(&loc, state, |
| "`%s' cannot be marked invariant; interfaces between " |
| "shader stages only.", decl->identifier); |
| } else if (earlier->data.used) { |
| _mesa_glsl_error(& loc, state, |
| "variable `%s' may not be redeclared " |
| "`invariant' after being used", |
| earlier->name); |
| } else { |
| earlier->data.invariant = true; |
| } |
| } |
| |
| /* Invariant redeclarations do not have r-values. |
| */ |
| return NULL; |
| } |
| |
| if (this->precise) { |
| assert(this->type == NULL); |
| |
| foreach_list_typed (ast_declaration, decl, link, &this->declarations) { |
| assert(decl->array_specifier == NULL); |
| assert(decl->initializer == NULL); |
| |
| ir_variable *const earlier = |
| state->symbols->get_variable(decl->identifier); |
| if (earlier == NULL) { |
| _mesa_glsl_error(& loc, state, |
| "undeclared variable `%s' cannot be marked " |
| "precise", decl->identifier); |
| } else if (state->current_function != NULL && |
| !state->symbols->name_declared_this_scope(decl->identifier)) { |
| /* Note: we have to check if we're in a function, since |
| * builtins are treated as having come from another scope. |
| */ |
| _mesa_glsl_error(& loc, state, |
| "variable `%s' from an outer scope may not be " |
| "redeclared `precise' in this scope", |
| earlier->name); |
| } else if (earlier->data.used) { |
| _mesa_glsl_error(& loc, state, |
| "variable `%s' may not be redeclared " |
| "`precise' after being used", |
| earlier->name); |
| } else { |
| earlier->data.precise = true; |
| } |
| } |
| |
| /* Precise redeclarations do not have r-values either. */ |
| return NULL; |
| } |
| |
| assert(this->type != NULL); |
| assert(!this->invariant); |
| assert(!this->precise); |
| |
| /* The type specifier may contain a structure definition. Process that |
| * before any of the variable declarations. |
| */ |
| (void) this->type->specifier->hir(instructions, state); |
| |
| decl_type = this->type->glsl_type(& type_name, state); |
| |
| /* Section 4.3.7 "Buffer Variables" of the GLSL 4.30 spec: |
| * "Buffer variables may only be declared inside interface blocks |
| * (section 4.3.9 “Interface Blocks”), which are then referred to as |
| * shader storage blocks. It is a compile-time error to declare buffer |
| * variables at global scope (outside a block)." |
| */ |
| if (type->qualifier.flags.q.buffer && !decl_type->is_interface()) { |
| _mesa_glsl_error(&loc, state, |
| "buffer variables cannot be declared outside " |
| "interface blocks"); |
| } |
| |
| /* An offset-qualified atomic counter declaration sets the default |
| * offset for the next declaration within the same atomic counter |
| * buffer. |
| */ |
| if (decl_type && decl_type->contains_atomic()) { |
| if (type->qualifier.flags.q.explicit_binding && |
| type->qualifier.flags.q.explicit_offset) |
| state->atomic_counter_offsets[type->qualifier.binding] = |
| type->qualifier.offset; |
| } |
| |
| if (this->declarations.is_empty()) { |
| /* If there is no structure involved in the program text, there are two |
| * possible scenarios: |
| * |
| * - The program text contained something like 'vec4;'. This is an |
| * empty declaration. It is valid but weird. Emit a warning. |
| * |
| * - The program text contained something like 'S;' and 'S' is not the |
| * name of a known structure type. This is both invalid and weird. |
| * Emit an error. |
| * |
| * - The program text contained something like 'mediump float;' |
| * when the programmer probably meant 'precision mediump |
| * float;' Emit a warning with a description of what they |
| * probably meant to do. |
| * |
| * Note that if decl_type is NULL and there is a structure involved, |
| * there must have been some sort of error with the structure. In this |
| * case we assume that an error was already generated on this line of |
| * code for the structure. There is no need to generate an additional, |
| * confusing error. |
| */ |
| assert(this->type->specifier->structure == NULL || decl_type != NULL |
| || state->error); |
| |
| if (decl_type == NULL) { |
| _mesa_glsl_error(&loc, state, |
| "invalid type `%s' in empty declaration", |
| type_name); |
| } else if (decl_type->base_type == GLSL_TYPE_ATOMIC_UINT) { |
| /* Empty atomic counter declarations are allowed and useful |
| * to set the default offset qualifier. |
| */ |
| return NULL; |
| } else if (this->type->qualifier.precision != ast_precision_none) { |
| if (this->type->specifier->structure != NULL) { |
| _mesa_glsl_error(&loc, state, |
| "precision qualifiers can't be applied " |
| "to structures"); |
| } else { |
| static const char *const precision_names[] = { |
| "highp", |
| "highp", |
| "mediump", |
| "lowp" |
| }; |
| |
| _mesa_glsl_warning(&loc, state, |
| "empty declaration with precision qualifier, " |
| "to set the default precision, use " |
| "`precision %s %s;'", |
| precision_names[this->type->qualifier.precision], |
| type_name); |
| } |
| } else if (this->type->specifier->structure == NULL) { |
| _mesa_glsl_warning(&loc, state, "empty declaration"); |
| } |
| } |
| |
| foreach_list_typed (ast_declaration, decl, link, &this->declarations) { |
| const struct glsl_type *var_type; |
| ir_variable *var; |
| const char *identifier = decl->identifier; |
| /* FINISHME: Emit a warning if a variable declaration shadows a |
| * FINISHME: declaration at a higher scope. |
| */ |
| |
| if ((decl_type == NULL) || decl_type->is_void()) { |
| if (type_name != NULL) { |
| _mesa_glsl_error(& loc, state, |
| "invalid type `%s' in declaration of `%s'", |
| type_name, decl->identifier); |
| } else { |
| _mesa_glsl_error(& loc, state, |
| "invalid type in declaration of `%s'", |
| decl->identifier); |
| } |
| continue; |
| } |
| |
| if (this->type->qualifier.flags.q.subroutine) { |
| const glsl_type *t; |
| const char *name; |
| |
| t = state->symbols->get_type(this->type->specifier->type_name); |
| if (!t) |
| _mesa_glsl_error(& loc, state, |
| "invalid type in declaration of `%s'", |
| decl->identifier); |
| name = ralloc_asprintf(ctx, "%s_%s", _mesa_shader_stage_to_subroutine_prefix(state->stage), decl->identifier); |
| |
| identifier = name; |
| |
| } |
| var_type = process_array_type(&loc, decl_type, decl->array_specifier, |
| state); |
| |
| var = new(ctx) ir_variable(var_type, identifier, ir_var_auto); |
| |
| /* The 'varying in' and 'varying out' qualifiers can only be used with |
| * ARB_geometry_shader4 and EXT_geometry_shader4, which we don't support |
| * yet. |
| */ |
| if (this->type->qualifier.flags.q.varying) { |
| if (this->type->qualifier.flags.q.in) { |
| _mesa_glsl_error(& loc, state, |
| "`varying in' qualifier in declaration of " |
| "`%s' only valid for geometry shaders using " |
| "ARB_geometry_shader4 or EXT_geometry_shader4", |
| decl->identifier); |
| } else if (this->type->qualifier.flags.q.out) { |
| _mesa_glsl_error(& loc, state, |
| "`varying out' qualifier in declaration of " |
| "`%s' only valid for geometry shaders using " |
| "ARB_geometry_shader4 or EXT_geometry_shader4", |
| decl->identifier); |
| } |
| } |
| |
| /* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification; |
| * |
| * "Global variables can only use the qualifiers const, |
| * attribute, uniform, or varying. Only one may be |
| * specified. |
| * |
| * Local variables can only use the qualifier const." |
| * |
| * This is relaxed in GLSL 1.30 and GLSL ES 3.00. It is also relaxed by |
| * any extension that adds the 'layout' keyword. |
| */ |
| if (!state->is_version(130, 300) |
| && !state->has_explicit_attrib_location() |
| && !state->has_separate_shader_objects() |
| && !state->ARB_fragment_coord_conventions_enable) { |
| if (this->type->qualifier.flags.q.out) { |
| _mesa_glsl_error(& loc, state, |
| "`out' qualifier in declaration of `%s' " |
| "only valid for function parameters in %s", |
| decl->identifier, state->get_version_string()); |
| } |
| if (this->type->qualifier.flags.q.in) { |
| _mesa_glsl_error(& loc, state, |
| "`in' qualifier in declaration of `%s' " |
| "only valid for function parameters in %s", |
| decl->identifier, state->get_version_string()); |
| } |
| /* FINISHME: Test for other invalid qualifiers. */ |
| } |
| |
| apply_type_qualifier_to_variable(& this->type->qualifier, var, state, |
| & loc, false); |
| |
| if (this->type->qualifier.flags.q.invariant) { |
| if (!is_varying_var(var, state->stage)) { |
| _mesa_glsl_error(&loc, state, |
| "`%s' cannot be marked invariant; interfaces between " |
| "shader stages only", var->name); |
| } |
| } |
| |
| if (state->current_function != NULL) { |
| const char *mode = NULL; |
| const char *extra = ""; |
| |
| /* There is no need to check for 'inout' here because the parser will |
| * only allow that in function parameter lists. |
| */ |
| if (this->type->qualifier.flags.q.attribute) { |
| mode = "attribute"; |
| } else if (this->type->qualifier.flags.q.subroutine) { |
| mode = "subroutine uniform"; |
| } else if (this->type->qualifier.flags.q.uniform) { |
| mode = "uniform"; |
| } else if (this->type->qualifier.flags.q.varying) { |
| mode = "varying"; |
| } else if (this->type->qualifier.flags.q.in) { |
| mode = "in"; |
| extra = " or in function parameter list"; |
| } else if (this->type->qualifier.flags.q.out) { |
| mode = "out"; |
| extra = " or in function parameter list"; |
| } |
| |
| if (mode) { |
| _mesa_glsl_error(& loc, state, |
| "%s variable `%s' must be declared at " |
| "global scope%s", |
| mode, var->name, extra); |
| } |
| } else if (var->data.mode == ir_var_shader_in) { |
| var->data.read_only = true; |
| |
| if (state->stage == MESA_SHADER_VERTEX) { |
| bool error_emitted = false; |
| |
| /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec: |
| * |
| * "Vertex shader inputs can only be float, floating-point |
| * vectors, matrices, signed and unsigned integers and integer |
| * vectors. Vertex shader inputs can also form arrays of these |
| * types, but not structures." |
| * |
| * From page 31 (page 27 of the PDF) of the GLSL 1.30 spec: |
| * |
| * "Vertex shader inputs can only be float, floating-point |
| * vectors, matrices, signed and unsigned integers and integer |
| * vectors. They cannot be arrays or structures." |
| * |
| * From page 23 (page 29 of the PDF) of the GLSL 1.20 spec: |
| * |
| * "The attribute qualifier can be used only with float, |
| * floating-point vectors, and matrices. Attribute variables |
| * cannot be declared as arrays or structures." |
| * |
| * From page 33 (page 39 of the PDF) of the GLSL ES 3.00 spec: |
| * |
| * "Vertex shader inputs can only be float, floating-point |
| * vectors, matrices, signed and unsigned integers and integer |
| * vectors. Vertex shader inputs cannot be arrays or |
| * structures." |
| */ |
| const glsl_type *check_type = var->type->without_array(); |
| |
| switch (check_type->base_type) { |
| case GLSL_TYPE_FLOAT: |
| break; |
| case GLSL_TYPE_UINT: |
| case GLSL_TYPE_INT: |
| if (state->is_version(120, 300)) |
| break; |
| case GLSL_TYPE_DOUBLE: |
| if (check_type->base_type == GLSL_TYPE_DOUBLE && (state->is_version(410, 0) || state->ARB_vertex_attrib_64bit_enable)) |
| break; |
| /* FALLTHROUGH */ |
| default: |
| _mesa_glsl_error(& loc, state, |
| "vertex shader input / attribute cannot have " |
| "type %s`%s'", |
| var->type->is_array() ? "array of " : "", |
| check_type->name); |
| error_emitted = true; |
| } |
| |
| if (!error_emitted && var->type->is_array() && |
| !state->check_version(150, 0, &loc, |
| "vertex shader input / attribute " |
| "cannot have array type")) { |
| error_emitted = true; |
| } |
| } else if (state->stage == MESA_SHADER_GEOMETRY) { |
| /* From section 4.3.4 (Inputs) of the GLSL 1.50 spec: |
| * |
| * Geometry shader input variables get the per-vertex values |
| * written out by vertex shader output variables of the same |
| * names. Since a geometry shader operates on a set of |
| * vertices, each input varying variable (or input block, see |
| * interface blocks below) needs to be declared as an array. |
| */ |
| if (!var->type->is_array()) { |
| _mesa_glsl_error(&loc, state, |
| "geometry shader inputs must be arrays"); |
| } |
| |
| handle_geometry_shader_input_decl(state, loc, var); |
| } else if (state->stage == MESA_SHADER_FRAGMENT) { |
| /* From section 4.3.4 (Input Variables) of the GLSL ES 3.10 spec: |
| * |
| * It is a compile-time error to declare a fragment shader |
| * input with, or that contains, any of the following types: |
| * |
| * * A boolean type |
| * * An opaque type |
| * * An array of arrays |
| * * An array of structures |
| * * A structure containing an array |
| * * A structure containing a structure |
| */ |
| if (state->es_shader) { |
| const glsl_type *check_type = var->type->without_array(); |
| if (check_type->is_boolean() || |
| check_type->contains_opaque()) { |
| _mesa_glsl_error(&loc, state, |
| "fragment shader input cannot have type %s", |
| check_type->name); |
| } |
| if (var->type->is_array() && |
| var->type->fields.array->is_array()) { |
| _mesa_glsl_error(&loc, state, |
| "%s shader output " |
| "cannot have an array of arrays", |
| _mesa_shader_stage_to_string(state->stage)); |
| } |
| if (var->type->is_array() && |
| var->type->fields.array->is_record()) { |
| _mesa_glsl_error(&loc, state, |
| "fragment shader input " |
| "cannot have an array of structs"); |
| } |
| if (var->type->is_record()) { |
| for (unsigned i = 0; i < var->type->length; i++) { |
| if (var->type->fields.structure[i].type->is_array() || |
| var->type->fields.structure[i].type->is_record()) |
| _mesa_glsl_error(&loc, state, |
| "fragement shader input cannot have " |
| "a struct that contains an " |
| "array or struct"); |
| } |
| } |
| } |
| } else if (state->stage == MESA_SHADER_TESS_CTRL || |
| state->stage == MESA_SHADER_TESS_EVAL) { |
| handle_tess_shader_input_decl(state, loc, var); |
| } |
| } else if (var->data.mode == ir_var_shader_out) { |
| const glsl_type *check_type = var->type->without_array(); |
| |
| /* From section 4.3.6 (Output variables) of the GLSL 4.40 spec: |
| * |
| * It is a compile-time error to declare a vertex, tessellation |
| * evaluation, tessellation control, or geometry shader output |
| * that contains any of the following: |
| * |
| * * A Boolean type (bool, bvec2 ...) |
| * * An opaque type |
| */ |
| if (check_type->is_boolean() || check_type->contains_opaque()) |
| _mesa_glsl_error(&loc, state, |
| "%s shader output cannot have type %s", |
| _mesa_shader_stage_to_string(state->stage), |
| check_type->name); |
| |
| /* From section 4.3.6 (Output variables) of the GLSL 4.40 spec: |
| * |
| * It is a compile-time error to declare a fragment shader output |
| * that contains any of the following: |
| * |
| * * A Boolean type (bool, bvec2 ...) |
| * * A double-precision scalar or vector (double, dvec2 ...) |
| * * An opaque type |
| * * Any matrix type |
| * * A structure |
| */ |
| if (state->stage == MESA_SHADER_FRAGMENT) { |
| if (check_type->is_record() || check_type->is_matrix()) |
| _mesa_glsl_error(&loc, state, |
| "fragment shader output " |
| "cannot have struct or matrix type"); |
| switch (check_type->base_type) { |
| case GLSL_TYPE_UINT: |
| case GLSL_TYPE_INT: |
| case GLSL_TYPE_FLOAT: |
| break; |
| default: |
| _mesa_glsl_error(&loc, state, |
| "fragment shader output cannot have " |
| "type %s", check_type->name); |
| } |
| } |
| |
| /* From section 4.3.6 (Output Variables) of the GLSL ES 3.10 spec: |
| * |
| * It is a compile-time error to declare a vertex shader output |
| * with, or that contains, any of the following types: |
| * |
| * * A boolean type |
| * * An opaque type |
| * * An array of arrays |
| * * An array of structures |
| * * A structure containing an array |
| * * A structure containing a structure |
| * |
| * It is a compile-time error to declare a fragment shader output |
| * with, or that contains, any of the following types: |
| * |
| * * A boolean type |
| * * An opaque type |
| * * A matrix |
| * * A structure |
| * * An array of array |
| */ |
| if (state->es_shader) { |
| if (var->type->is_array() && |
| var->type->fields.array->is_array()) { |
| _mesa_glsl_error(&loc, state, |
| "%s shader output " |
| "cannot have an array of arrays", |
| _mesa_shader_stage_to_string(state->stage)); |
| } |
| if (state->stage == MESA_SHADER_VERTEX) { |
| if (var->type->is_array() && |
| var->type->fields.array->is_record()) { |
| _mesa_glsl_error(&loc, state, |
| "vertex shader output " |
| "cannot have an array of structs"); |
| } |
| if (var->type->is_record()) { |
| for (unsigned i = 0; i < var->type->length; i++) { |
| if (var->type->fields.structure[i].type->is_array() || |
| var->type->fields.structure[i].type->is_record()) |
| _mesa_glsl_error(&loc, state, |
| "vertex shader output cannot have a " |
| "struct that contains an " |
| "array or struct"); |
| } |
| } |
| } |
| } |
| |
| if (state->stage == MESA_SHADER_TESS_CTRL) { |
| handle_tess_ctrl_shader_output_decl(state, loc, var); |
| } |
| } else if (var->type->contains_subroutine()) { |
| /* declare subroutine uniforms as hidden */ |
| var->data.how_declared = ir_var_hidden; |
| } |
| |
| /* Integer fragment inputs must be qualified with 'flat'. In GLSL ES, |
| * so must integer vertex outputs. |
| * |
| * From section 4.3.4 ("Inputs") of the GLSL 1.50 spec: |
| * "Fragment shader inputs that are signed or unsigned integers or |
| * integer vectors must be qualified with the interpolation qualifier |
| * flat." |
| * |
| * From section 4.3.4 ("Input Variables") of the GLSL 3.00 ES spec: |
| * "Fragment shader inputs that are, or contain, signed or unsigned |
| * integers or integer vectors must be qualified with the |
| * interpolation qualifier flat." |
| * |
| * From section 4.3.6 ("Output Variables") of the GLSL 3.00 ES spec: |
| * "Vertex shader outputs that are, or contain, signed or unsigned |
| * integers or integer vectors must be qualified with the |
| * interpolation qualifier flat." |
| * |
| * Note that prior to GLSL 1.50, this requirement applied to vertex |
| * outputs rather than fragment inputs. That creates problems in the |
| * presence of geometry shaders, so we adopt the GLSL 1.50 rule for all |
| * desktop GL shaders. For GLSL ES shaders, we follow the spec and |
| * apply the restriction to both vertex outputs and fragment inputs. |
| * |
| * Note also that the desktop GLSL specs are missing the text "or |
| * contain"; this is presumably an oversight, since there is no |
| * reasonable way to interpolate a fragment shader input that contains |
| * an integer. |
| */ |
| if (state->is_version(130, 300) && |
| var->type->contains_integer() && |
| var->data.interpolation != INTERP_QUALIFIER_FLAT && |
| ((state->stage == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_in) |
| || (state->stage == MESA_SHADER_VERTEX && var->data.mode == ir_var_shader_out |
| && state->es_shader))) { |
| const char *var_type = (state->stage == MESA_SHADER_VERTEX) ? |
| "vertex output" : "fragment input"; |
| _mesa_glsl_error(&loc, state, "if a %s is (or contains) " |
| "an integer, then it must be qualified with 'flat'", |
| var_type); |
| } |
| |
| /* Double fragment inputs must be qualified with 'flat'. */ |
| if (var->type->contains_double() && |
| var->data.interpolation != INTERP_QUALIFIER_FLAT && |
| state->stage == MESA_SHADER_FRAGMENT && |
| var->data.mode == ir_var_shader_in) { |
| _mesa_glsl_error(&loc, state, "if a fragment input is (or contains) " |
| "a double, then it must be qualified with 'flat'", |
| var_type); |
| } |
| |
| /* Interpolation qualifiers cannot be applied to 'centroid' and |
| * 'centroid varying'. |
| * |
| * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec: |
| * "interpolation qualifiers may only precede the qualifiers in, |
| * centroid in, out, or centroid out in a declaration. They do not apply |
| * to the deprecated storage qualifiers varying or centroid varying." |
| * |
| * These deprecated storage qualifiers do not exist in GLSL ES 3.00. |
| */ |
| if (state->is_version(130, 0) |
| && this->type->qualifier.has_interpolation() |
| && this->type->qualifier.flags.q.varying) { |
| |
| const char *i = this->type->qualifier.interpolation_string(); |
| assert(i != NULL); |
| const char *s; |
| if (this->type->qualifier.flags.q.centroid) |
| s = "centroid varying"; |
| else |
| s = "varying"; |
| |
| _mesa_glsl_error(&loc, state, |
| "qualifier '%s' cannot be applied to the " |
| "deprecated storage qualifier '%s'", i, s); |
| } |
| |
| |
| /* Interpolation qualifiers can only apply to vertex shader outputs and |
| * fragment shader inputs. |
| * |
| * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec: |
| * "Outputs from a vertex shader (out) and inputs to a fragment |
| * shader (in) can be further qualified with one or more of these |
| * interpolation qualifiers" |
| * |
| * From page 31 (page 37 of the PDF) of the GLSL ES 3.00 spec: |
| * "These interpolation qualifiers may only precede the qualifiers |
| * in, centroid in, out, or centroid out in a declaration. They do |
| * not apply to inputs into a vertex shader or outputs from a |
| * fragment shader." |
| */ |
| if (state->is_version(130, 300) |
| && this->type->qualifier.has_interpolation()) { |
| |
| const char *i = this->type->qualifier.interpolation_string(); |
| assert(i != NULL); |
| |
| switch (state->stage) { |
| case MESA_SHADER_VERTEX: |
| if (this->type->qualifier.flags.q.in) { |
| _mesa_glsl_error(&loc, state, |
| "qualifier '%s' cannot be applied to vertex " |
| "shader inputs", i); |
| } |
| break; |
| case MESA_SHADER_FRAGMENT: |
| if (this->type->qualifier.flags.q.out) { |
| _mesa_glsl_error(&loc, state, |
| "qualifier '%s' cannot be applied to fragment " |
| "shader outputs", i); |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| |
| |
| /* From section 4.3.4 of the GLSL 4.00 spec: |
| * "Input variables may not be declared using the patch in qualifier |
| * in tessellation control or geometry shaders." |
| * |
| * From section 4.3.6 of the GLSL 4.00 spec: |
| * "It is an error to use patch out in a vertex, tessellation |
| * evaluation, or geometry shader." |
| * |
| * This doesn't explicitly forbid using them in a fragment shader, but |
| * that's probably just an oversight. |
| */ |
| if (state->stage != MESA_SHADER_TESS_EVAL |
| && this->type->qualifier.flags.q.patch |
| && this->type->qualifier.flags.q.in) { |
| |
| _mesa_glsl_error(&loc, state, "'patch in' can only be used in a " |
| "tessellation evaluation shader"); |
| } |
| |
| if (state->stage != MESA_SHADER_TESS_CTRL |
| && this->type->qualifier.flags.q.patch |
| && this->type->qualifier.flags.q.out) { |
| |
| _mesa_glsl_error(&loc, state, "'patch out' can only be used in a " |
| "tessellation control shader"); |
| } |
| |
| /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30. |
| */ |
| if (this->type->qualifier.precision != ast_precision_none) { |
| state->check_precision_qualifiers_allowed(&loc); |
| } |
| |
| |
| /* If a precision qualifier is allowed on a type, it is allowed on |
| * an array of that type. |
| */ |
| if (!(this->type->qualifier.precision == ast_precision_none |
| || precision_qualifier_allowed(var->type->without_array()))) { |
| |
| _mesa_glsl_error(&loc, state, |
| "precision qualifiers apply only to floating point" |
| ", integer and opaque types"); |
| } |
| |
| /* From section 4.1.7 of the GLSL 4.40 spec: |
| * |
| * "[Opaque types] can only be declared as function |
| * parameters or uniform-qualified variables." |
| */ |
| if (var_type->contains_opaque() && |
| !this->type->qualifier.flags.q.uniform) { |
| _mesa_glsl_error(&loc, state, |
| "opaque variables must be declared uniform"); |
| } |
| |
| /* Process the initializer and add its instructions to a temporary |
| * list. This list will be added to the instruction stream (below) after |
| * the declaration is added. This is done because in some cases (such as |
| * redeclarations) the declaration may not actually be added to the |
| * instruction stream. |
| */ |
| exec_list initializer_instructions; |
| |
| /* Examine var name here since var may get deleted in the next call */ |
| bool var_is_gl_id = is_gl_identifier(var->name); |
| |
| ir_variable *earlier = |
| get_variable_being_redeclared(var, decl->get_location(), state, |
| false /* allow_all_redeclarations */); |
| if (earlier != NULL) { |
| if (var_is_gl_id && |
| earlier->data.how_declared == ir_var_declared_in_block) { |
| _mesa_glsl_error(&loc, state, |
| "`%s' has already been redeclared using " |
| "gl_PerVertex", earlier->name); |
| } |
| earlier->data.how_declared = ir_var_declared_normally; |
| } |
| |
| if (decl->initializer != NULL) { |
| result = process_initializer((earlier == NULL) ? var : earlier, |
| decl, this->type, |
| &initializer_instructions, state); |
| } |
| |
| /* From page 23 (page 29 of the PDF) of the GLSL 1.10 spec: |
| * |
| * "It is an error to write to a const variable outside of |
| * its declaration, so they must be initialized when |
| * declared." |
| */ |
| if (this->type->qualifier.flags.q.constant && decl->initializer == NULL) { |
| _mesa_glsl_error(& loc, state, |
| "const declaration of `%s' must be initialized", |
| decl->identifier); |
| } |
| |
| if (state->es_shader) { |
| const glsl_type *const t = (earlier == NULL) |
| ? var->type : earlier->type; |
| |
| if (t->is_unsized_array()) |
| /* Section 10.17 of the GLSL ES 1.00 specification states that |
| * unsized array declarations have been removed from the language. |
| * Arrays that are sized using an initializer are still explicitly |
| * sized. However, GLSL ES 1.00 does not allow array |
| * initializers. That is only allowed in GLSL ES 3.00. |
| * |
| * Section 4.1.9 (Arrays) of the GLSL ES 3.00 spec says: |
| * |
| * "An array type can also be formed without specifying a size |
| * if the definition includes an initializer: |
| * |
| * float x[] = float[2] (1.0, 2.0); // declares an array of size 2 |
| * float y[] = float[] (1.0, 2.0, 3.0); // declares an array of size 3 |
| * |
| * float a[5]; |
| * float b[] = a;" |
| */ |
| _mesa_glsl_error(& loc, state, |
| "unsized array declarations are not allowed in " |
| "GLSL ES"); |
| } |
| |
| /* If the declaration is not a redeclaration, there are a few additional |
| * semantic checks that must be applied. In addition, variable that was |
| * created for the declaration should be added to the IR stream. |
| */ |
| if (earlier == NULL) { |
| validate_identifier(decl->identifier, loc, state); |
| |
| /* Add the variable to the symbol table. Note that the initializer's |
| * IR was already processed earlier (though it hasn't been emitted |
| * yet), without the variable in scope. |
| * |
| * This differs from most C-like languages, but it follows the GLSL |
| * specification. From page 28 (page 34 of the PDF) of the GLSL 1.50 |
| * spec: |
| * |
| * "Within a declaration, the scope of a name starts immediately |
| * after the initializer if present or immediately after the name |
| * being declared if not." |
| */ |
| if (!state->symbols->add_variable(var)) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(&loc, state, "name `%s' already taken in the " |
| "current scope", decl->identifier); |
| continue; |
| } |
| |
| /* Push the variable declaration to the top. It means that all the |
| * variable declarations will appear in a funny last-to-first order, |
| * but otherwise we run into trouble if a function is prototyped, a |
| * global var is decled, then the function is defined with usage of |
| * the global var. See glslparsertest's CorrectModule.frag. |
| */ |
| instructions->push_head(var); |
| } |
| |
| instructions->append_list(&initializer_instructions); |
| } |
| |
| |
| /* Generally, variable declarations do not have r-values. However, |
| * one is used for the declaration in |
| * |
| * while (bool b = some_condition()) { |
| * ... |
| * } |
| * |
| * so we return the rvalue from the last seen declaration here. |
| */ |
| return result; |
| } |
| |
| |
| ir_rvalue * |
| ast_parameter_declarator::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| void *ctx = state; |
| const struct glsl_type *type; |
| const char *name = NULL; |
| YYLTYPE loc = this->get_location(); |
| |
| type = this->type->glsl_type(& name, state); |
| |
| if (type == NULL) { |
| if (name != NULL) { |
| _mesa_glsl_error(& loc, state, |
| "invalid type `%s' in declaration of `%s'", |
| name, this->identifier); |
| } else { |
| _mesa_glsl_error(& loc, state, |
| "invalid type in declaration of `%s'", |
| this->identifier); |
| } |
| |
| type = glsl_type::error_type; |
| } |
| |
| /* From page 62 (page 68 of the PDF) of the GLSL 1.50 spec: |
| * |
| * "Functions that accept no input arguments need not use void in the |
| * argument list because prototypes (or definitions) are required and |
| * therefore there is no ambiguity when an empty argument list "( )" is |
| * declared. The idiom "(void)" as a parameter list is provided for |
| * convenience." |
| * |
| * Placing this check here prevents a void parameter being set up |
| * for a function, which avoids tripping up checks for main taking |
| * parameters and lookups of an unnamed symbol. |
| */ |
| if (type->is_void()) { |
| if (this->identifier != NULL) |
| _mesa_glsl_error(& loc, state, |
| "named parameter cannot have type `void'"); |
| |
| is_void = true; |
| return NULL; |
| } |
| |
| if (formal_parameter && (this->identifier == NULL)) { |
| _mesa_glsl_error(& loc, state, "formal parameter lacks a name"); |
| return NULL; |
| } |
| |
| /* This only handles "vec4 foo[..]". The earlier specifier->glsl_type(...) |
| * call already handled the "vec4[..] foo" case. |
| */ |
| type = process_array_type(&loc, type, this->array_specifier, state); |
| |
| if (!type->is_error() && type->is_unsized_array()) { |
| _mesa_glsl_error(&loc, state, "arrays passed as parameters must have " |
| "a declared size"); |
| type = glsl_type::error_type; |
| } |
| |
| is_void = false; |
| ir_variable *var = new(ctx) |
| ir_variable(type, this->identifier, ir_var_function_in); |
| |
| /* Apply any specified qualifiers to the parameter declaration. Note that |
| * for function parameters the default mode is 'in'. |
| */ |
| apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc, |
| true); |
| |
| /* From section 4.1.7 of the GLSL 4.40 spec: |
| * |
| * "Opaque variables cannot be treated as l-values; hence cannot |
| * be used as out or inout function parameters, nor can they be |
| * assigned into." |
| */ |
| if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out) |
| && type->contains_opaque()) { |
| _mesa_glsl_error(&loc, state, "out and inout parameters cannot " |
| "contain opaque variables"); |
| type = glsl_type::error_type; |
| } |
| |
| /* From page 39 (page 45 of the PDF) of the GLSL 1.10 spec: |
| * |
| * "When calling a function, expressions that do not evaluate to |
| * l-values cannot be passed to parameters declared as out or inout." |
| * |
| * From page 32 (page 38 of the PDF) of the GLSL 1.10 spec: |
| * |
| * "Other binary or unary expressions, non-dereferenced arrays, |
| * function names, swizzles with repeated fields, and constants |
| * cannot be l-values." |
| * |
| * So for GLSL 1.10, passing an array as an out or inout parameter is not |
| * allowed. This restriction is removed in GLSL 1.20, and in GLSL ES. |
| */ |
| if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out) |
| && type->is_array() |
| && !state->check_version(120, 100, &loc, |
| "arrays cannot be out or inout parameters")) { |
| type = glsl_type::error_type; |
| } |
| |
| instructions->push_tail(var); |
| |
| /* Parameter declarations do not have r-values. |
| */ |
| return NULL; |
| } |
| |
| |
| void |
| ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters, |
| bool formal, |
| exec_list *ir_parameters, |
| _mesa_glsl_parse_state *state) |
| { |
| ast_parameter_declarator *void_param = NULL; |
| unsigned count = 0; |
| |
| foreach_list_typed (ast_parameter_declarator, param, link, ast_parameters) { |
| param->formal_parameter = formal; |
| param->hir(ir_parameters, state); |
| |
| if (param->is_void) |
| void_param = param; |
| |
| count++; |
| } |
| |
| if ((void_param != NULL) && (count > 1)) { |
| YYLTYPE loc = void_param->get_location(); |
| |
| _mesa_glsl_error(& loc, state, |
| "`void' parameter must be only parameter"); |
| } |
| } |
| |
| |
| void |
| emit_function(_mesa_glsl_parse_state *state, ir_function *f) |
| { |
| /* IR invariants disallow function declarations or definitions |
| * nested within other function definitions. But there is no |
| * requirement about the relative order of function declarations |
| * and definitions with respect to one another. So simply insert |
| * the new ir_function block at the end of the toplevel instruction |
| * list. |
| */ |
| state->toplevel_ir->push_tail(f); |
| } |
| |
| |
| ir_rvalue * |
| ast_function::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| void *ctx = state; |
| ir_function *f = NULL; |
| ir_function_signature *sig = NULL; |
| exec_list hir_parameters; |
| YYLTYPE loc = this->get_location(); |
| |
| const char *const name = identifier; |
| |
| /* New functions are always added to the top-level IR instruction stream, |
| * so this instruction list pointer is ignored. See also emit_function |
| * (called below). |
| */ |
| (void) instructions; |
| |
| /* From page 21 (page 27 of the PDF) of the GLSL 1.20 spec, |
| * |
| * "Function declarations (prototypes) cannot occur inside of functions; |
| * they must be at global scope, or for the built-in functions, outside |
| * the global scope." |
| * |
| * From page 27 (page 33 of the PDF) of the GLSL ES 1.00.16 spec, |
| * |
| * "User defined functions may only be defined within the global scope." |
| * |
| * Note that this language does not appear in GLSL 1.10. |
| */ |
| if ((state->current_function != NULL) && |
| state->is_version(120, 100)) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(&loc, state, |
| "declaration of function `%s' not allowed within " |
| "function body", name); |
| } |
| |
| validate_identifier(name, this->get_location(), state); |
| |
| /* Convert the list of function parameters to HIR now so that they can be |
| * used below to compare this function's signature with previously seen |
| * signatures for functions with the same name. |
| */ |
| ast_parameter_declarator::parameters_to_hir(& this->parameters, |
| is_definition, |
| & hir_parameters, state); |
| |
| const char *return_type_name; |
| const glsl_type *return_type = |
| this->return_type->glsl_type(& return_type_name, state); |
| |
| if (!return_type) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(&loc, state, |
| "function `%s' has undeclared return type `%s'", |
| name, return_type_name); |
| return_type = glsl_type::error_type; |
| } |
| |
| /* ARB_shader_subroutine states: |
| * "Subroutine declarations cannot be prototyped. It is an error to prepend |
| * subroutine(...) to a function declaration." |
| */ |
| if (this->return_type->qualifier.flags.q.subroutine_def && !is_definition) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(&loc, state, |
| "function declaration `%s' cannot have subroutine prepended", |
| name); |
| } |
| |
| /* From page 56 (page 62 of the PDF) of the GLSL 1.30 spec: |
| * "No qualifier is allowed on the return type of a function." |
| */ |
| if (this->return_type->has_qualifiers()) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(& loc, state, |
| "function `%s' return type has qualifiers", name); |
| } |
| |
| /* Section 6.1 (Function Definitions) of the GLSL 1.20 spec says: |
| * |
| * "Arrays are allowed as arguments and as the return type. In both |
| * cases, the array must be explicitly sized." |
| */ |
| if (return_type->is_unsized_array()) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(& loc, state, |
| "function `%s' return type array must be explicitly " |
| "sized", name); |
| } |
| |
| /* From section 4.1.7 of the GLSL 4.40 spec: |
| * |
| * "[Opaque types] can only be declared as function parameters |
| * or uniform-qualified variables." |
| */ |
| if (return_type->contains_opaque()) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(&loc, state, |
| "function `%s' return type can't contain an opaque type", |
| name); |
| } |
| |
| /* Create an ir_function if one doesn't already exist. */ |
| f = state->symbols->get_function(name); |
| if (f == NULL) { |
| f = new(ctx) ir_function(name); |
| if (!this->return_type->qualifier.flags.q.subroutine) { |
| if (!state->symbols->add_function(f)) { |
| /* This function name shadows a non-function use of the same name. */ |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(&loc, state, "function name `%s' conflicts with " |
| "non-function", name); |
| return NULL; |
| } |
| } |
| emit_function(state, f); |
| } |
| |
| /* From GLSL ES 3.0 spec, chapter 6.1 "Function Definitions", page 71: |
| * |
| * "A shader cannot redefine or overload built-in functions." |
| * |
| * While in GLSL ES 1.0 specification, chapter 8 "Built-in Functions": |
| * |
| * "User code can overload the built-in functions but cannot redefine |
| * them." |
| */ |
| if (state->es_shader && state->language_version >= 300) { |
| /* Local shader has no exact candidates; check the built-ins. */ |
| _mesa_glsl_initialize_builtin_functions(); |
| if (_mesa_glsl_find_builtin_function_by_name(name)) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(& loc, state, |
| "A shader cannot redefine or overload built-in " |
| "function `%s' in GLSL ES 3.00", name); |
| return NULL; |
| } |
| } |
| |
| /* Verify that this function's signature either doesn't match a previously |
| * seen signature for a function with the same name, or, if a match is found, |
| * that the previously seen signature does not have an associated definition. |
| */ |
| if (state->es_shader || f->has_user_signature()) { |
| sig = f->exact_matching_signature(state, &hir_parameters); |
| if (sig != NULL) { |
| const char *badvar = sig->qualifiers_match(&hir_parameters); |
| if (badvar != NULL) { |
| YYLTYPE loc = this->get_location(); |
| |
| _mesa_glsl_error(&loc, state, "function `%s' parameter `%s' " |
| "qualifiers don't match prototype", name, badvar); |
| } |
| |
| if (sig->return_type != return_type) { |
| YYLTYPE loc = this->get_location(); |
| |
| _mesa_glsl_error(&loc, state, "function `%s' return type doesn't " |
| "match prototype", name); |
| } |
| |
| if (sig->is_defined) { |
| if (is_definition) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(& loc, state, "function `%s' redefined", name); |
| } else { |
| /* We just encountered a prototype that exactly matches a |
| * function that's already been defined. This is redundant, |
| * and we should ignore it. |
| */ |
| return NULL; |
| } |
| } |
| } |
| } |
| |
| /* Verify the return type of main() */ |
| if (strcmp(name, "main") == 0) { |
| if (! return_type->is_void()) { |
| YYLTYPE loc = this->get_location(); |
| |
| _mesa_glsl_error(& loc, state, "main() must return void"); |
| } |
| |
| if (!hir_parameters.is_empty()) { |
| YYLTYPE loc = this->get_location(); |
| |
| _mesa_glsl_error(& loc, state, "main() must not take any parameters"); |
| } |
| } |
| |
| /* Finish storing the information about this new function in its signature. |
| */ |
| if (sig == NULL) { |
| sig = new(ctx) ir_function_signature(return_type); |
| f->add_signature(sig); |
| } |
| |
| sig->replace_parameters(&hir_parameters); |
| signature = sig; |
| |
| if (this->return_type->qualifier.flags.q.subroutine_def) { |
| int idx; |
| |
| f->num_subroutine_types = this->return_type->qualifier.subroutine_list->declarations.length(); |
| f->subroutine_types = ralloc_array(state, const struct glsl_type *, |
| f->num_subroutine_types); |
| idx = 0; |
| foreach_list_typed(ast_declaration, decl, link, &this->return_type->qualifier.subroutine_list->declarations) { |
| const struct glsl_type *type; |
| /* the subroutine type must be already declared */ |
| type = state->symbols->get_type(decl->identifier); |
| if (!type) { |
| _mesa_glsl_error(& loc, state, "unknown type '%s' in subroutine function definition", decl->identifier); |
| } |
| f->subroutine_types[idx++] = type; |
| } |
| state->subroutines = (ir_function **)reralloc(state, state->subroutines, |
| ir_function *, |
| state->num_subroutines + 1); |
| state->subroutines[state->num_subroutines] = f; |
| state->num_subroutines++; |
| |
| } |
| |
| if (this->return_type->qualifier.flags.q.subroutine) { |
| if (!state->symbols->add_type(this->identifier, glsl_type::get_subroutine_instance(this->identifier))) { |
| _mesa_glsl_error(& loc, state, "type '%s' previously defined", this->identifier); |
| return NULL; |
| } |
| state->subroutine_types = (ir_function **)reralloc(state, state->subroutine_types, |
| ir_function *, |
| state->num_subroutine_types + 1); |
| state->subroutine_types[state->num_subroutine_types] = f; |
| state->num_subroutine_types++; |
| |
| f->is_subroutine = true; |
| } |
| |
| /* Function declarations (prototypes) do not have r-values. |
| */ |
| return NULL; |
| } |
| |
| |
| ir_rvalue * |
| ast_function_definition::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| prototype->is_definition = true; |
| prototype->hir(instructions, state); |
| |
| ir_function_signature *signature = prototype->signature; |
| if (signature == NULL) |
| return NULL; |
| |
| assert(state->current_function == NULL); |
| state->current_function = signature; |
| state->found_return = false; |
| |
| /* Duplicate parameters declared in the prototype as concrete variables. |
| * Add these to the symbol table. |
| */ |
| state->symbols->push_scope(); |
| foreach_in_list(ir_variable, var, &signature->parameters) { |
| assert(var->as_variable() != NULL); |
| |
| /* The only way a parameter would "exist" is if two parameters have |
| * the same name. |
| */ |
| if (state->symbols->name_declared_this_scope(var->name)) { |
| YYLTYPE loc = this->get_location(); |
| |
| _mesa_glsl_error(& loc, state, "parameter `%s' redeclared", var->name); |
| } else { |
| state->symbols->add_variable(var); |
| } |
| } |
| |
| /* Convert the body of the function to HIR. */ |
| this->body->hir(&signature->body, state); |
| signature->is_defined = true; |
| |
| state->symbols->pop_scope(); |
| |
| assert(state->current_function == signature); |
| state->current_function = NULL; |
| |
| if (!signature->return_type->is_void() && !state->found_return) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(& loc, state, "function `%s' has non-void return type " |
| "%s, but no return statement", |
| signature->function_name(), |
| signature->return_type->name); |
| } |
| |
| /* Function definitions do not have r-values. |
| */ |
| return NULL; |
| } |
| |
| |
| ir_rvalue * |
| ast_jump_statement::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| void *ctx = state; |
| |
| switch (mode) { |
| case ast_return: { |
| ir_return *inst; |
| assert(state->current_function); |
| |
| if (opt_return_value) { |
| ir_rvalue *ret = opt_return_value->hir(instructions, state); |
| |
| /* 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 prior to |
| * ARB_shading_language_420pack. |
| */ |
| if (state->current_function->return_type != ret_type) { |
| YYLTYPE loc = this->get_location(); |
| |
| if (state->ARB_shading_language_420pack_enable) { |
| if (!apply_implicit_conversion(state->current_function->return_type, |
| ret, state)) { |
| _mesa_glsl_error(& loc, state, |
| "could not implicitly convert return value " |
| "to %s, in function `%s'", |
| state->current_function->return_type->name, |
| state->current_function->function_name()); |
| } |
| } else { |
| _mesa_glsl_error(& loc, state, |
| "`return' with wrong type %s, in function `%s' " |
| "returning %s", |
| ret_type->name, |
| state->current_function->function_name(), |
| state->current_function->return_type->name); |
| } |
| } else if (state->current_function->return_type->base_type == |
| GLSL_TYPE_VOID) { |
| YYLTYPE loc = this->get_location(); |
| |
| /* The ARB_shading_language_420pack, GLSL ES 3.0, and GLSL 4.20 |
| * specs add a clarification: |
| * |
| * "A void function can only use return without a return argument, even if |
| * the return argument has void type. Return statements only accept values: |
| * |
| * void func1() { } |
| * void func2() { return func1(); } // illegal return statement" |
| */ |
| _mesa_glsl_error(& loc, state, |
| "void functions can only use `return' without a " |
| "return argument"); |
| } |
| |
| inst = new(ctx) ir_return(ret); |
| } else { |
| if (state->current_function->return_type->base_type != |
| GLSL_TYPE_VOID) { |
| YYLTYPE loc = this->get_location(); |
| |
| _mesa_glsl_error(& loc, state, |
| "`return' with no value, in function %s returning " |
| "non-void", |
| state->current_function->function_name()); |
| } |
| inst = new(ctx) ir_return; |
| } |
| |
| state->found_return = true; |
| instructions->push_tail(inst); |
| break; |
| } |
| |
| case ast_discard: |
| if (state->stage != MESA_SHADER_FRAGMENT) { |
| YYLTYPE loc = this->get_location(); |
| |
| _mesa_glsl_error(& loc, state, |
| "`discard' may only appear in a fragment shader"); |
| } |
| instructions->push_tail(new(ctx) ir_discard); |
| break; |
| |
| case ast_break: |
| case ast_continue: |
| if (mode == ast_continue && |
| state->loop_nesting_ast == NULL) { |
| YYLTYPE loc = this->get_location(); |
| |
| _mesa_glsl_error(& loc, state, "continue may only appear in a loop"); |
| } else if (mode == ast_break && |
| state->loop_nesting_ast == NULL && |
| state->switch_state.switch_nesting_ast == NULL) { |
| YYLTYPE loc = this->get_location(); |
| |
| _mesa_glsl_error(& loc, state, |
| "break may only appear in a loop or a switch"); |
| } else { |
| /* For a loop, inline the for loop expression again, since we don't |
| * know where near the end of the loop body the normal copy of it is |
| * going to be placed. Same goes for the condition for a do-while |
| * loop. |
| */ |
| if (state->loop_nesting_ast != NULL && |
| mode == ast_continue && !state->switch_state.is_switch_innermost) { |
| if (state->loop_nesting_ast->rest_expression) { |
| state->loop_nesting_ast->rest_expression->hir(instructions, |
| state); |
| } |
| if (state->loop_nesting_ast->mode == |
| ast_iteration_statement::ast_do_while) { |
| state->loop_nesting_ast->condition_to_hir(instructions, state); |
| } |
| } |
| |
| if (state->switch_state.is_switch_innermost && |
| mode == ast_continue) { |
| /* Set 'continue_inside' to true. */ |
| ir_rvalue *const true_val = new (ctx) ir_constant(true); |
| ir_dereference_variable *deref_continue_inside_var = |
| new(ctx) ir_dereference_variable(state->switch_state.continue_inside); |
| instructions->push_tail(new(ctx) ir_assignment(deref_continue_inside_var, |
| true_val)); |
| |
| /* Break out from the switch, continue for the loop will |
| * be called right after switch. */ |
| ir_loop_jump *const jump = |
| new(ctx) ir_loop_jump(ir_loop_jump::jump_break); |
| instructions->push_tail(jump); |
| |
| } else if (state->switch_state.is_switch_innermost && |
| mode == ast_break) { |
| /* Force break out of switch by inserting a break. */ |
| ir_loop_jump *const jump = |
| new(ctx) ir_loop_jump(ir_loop_jump::jump_break); |
| instructions->push_tail(jump); |
| } else { |
| ir_loop_jump *const jump = |
| new(ctx) ir_loop_jump((mode == ast_break) |
| ? ir_loop_jump::jump_break |
| : ir_loop_jump::jump_continue); |
| instructions->push_tail(jump); |
| } |
| } |
| |
| break; |
| } |
| |
| /* Jump instructions do not have r-values. |
| */ |
| return NULL; |
| } |
| |
| |
| ir_rvalue * |
| ast_selection_statement::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| void *ctx = state; |
| |
| ir_rvalue *const condition = this->condition->hir(instructions, state); |
| |
| /* From page 66 (page 72 of the PDF) of the GLSL 1.50 spec: |
| * |
| * "Any expression whose type evaluates to a Boolean can be used as the |
| * conditional expression bool-expression. Vector types are not accepted |
| * as the expression to if." |
| * |
| * The checks are separated so that higher quality diagnostics can be |
| * generated for cases where both rules are violated. |
| */ |
| if (!condition->type->is_boolean() || !condition->type->is_scalar()) { |
| YYLTYPE loc = this->condition->get_location(); |
| |
| _mesa_glsl_error(& loc, state, "if-statement condition must be scalar " |
| "boolean"); |
| } |
| |
| ir_if *const stmt = new(ctx) ir_if(condition); |
| |
| if (then_statement != NULL) { |
| state->symbols->push_scope(); |
| then_statement->hir(& stmt->then_instructions, state); |
| state->symbols->pop_scope(); |
| } |
| |
| if (else_statement != NULL) { |
| state->symbols->push_scope(); |
| else_statement->hir(& stmt->else_instructions, state); |
| state->symbols->pop_scope(); |
| } |
| |
| instructions->push_tail(stmt); |
| |
| /* if-statements do not have r-values. |
| */ |
| return NULL; |
| } |
| |
| |
| ir_rvalue * |
| ast_switch_statement::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| void *ctx = state; |
| |
| ir_rvalue *const test_expression = |
| this->test_expression->hir(instructions, state); |
| |
| /* From page 66 (page 55 of the PDF) of the GLSL 1.50 spec: |
| * |
| * "The type of init-expression in a switch statement must be a |
| * scalar integer." |
| */ |
| if (!test_expression->type->is_scalar() || |
| !test_expression->type->is_integer()) { |
| YYLTYPE loc = this->test_expression->get_location(); |
| |
| _mesa_glsl_error(& loc, |
| state, |
| "switch-statement expression must be scalar " |
| "integer"); |
| } |
| |
| /* Track the switch-statement nesting in a stack-like manner. |
| */ |
| struct glsl_switch_state saved = state->switch_state; |
| |
| state->switch_state.is_switch_innermost = true; |
| state->switch_state.switch_nesting_ast = this; |
| state->switch_state.labels_ht = hash_table_ctor(0, hash_table_pointer_hash, |
| hash_table_pointer_compare); |
| state->switch_state.previous_default = NULL; |
| |
| /* Initalize is_fallthru state to false. |
| */ |
| ir_rvalue *const is_fallthru_val = new (ctx) ir_constant(false); |
| state->switch_state.is_fallthru_var = |
| new(ctx) ir_variable(glsl_type::bool_type, |
| "switch_is_fallthru_tmp", |
| ir_var_temporary); |
| instructions->push_tail(state->switch_state.is_fallthru_var); |
| |
| ir_dereference_variable *deref_is_fallthru_var = |
| new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var); |
| instructions->push_tail(new(ctx) ir_assignment(deref_is_fallthru_var, |
| is_fallthru_val)); |
| |
| /* Initialize continue_inside state to false. |
| */ |
| state->switch_state.continue_inside = |
| new(ctx) ir_variable(glsl_type::bool_type, |
| "continue_inside_tmp", |
| ir_var_temporary); |
| instructions->push_tail(state->switch_state.continue_inside); |
| |
| ir_rvalue *const false_val = new (ctx) ir_constant(false); |
| ir_dereference_variable *deref_continue_inside_var = |
| new(ctx) ir_dereference_variable(state->switch_state.continue_inside); |
| instructions->push_tail(new(ctx) ir_assignment(deref_continue_inside_var, |
| false_val)); |
| |
| state->switch_state.run_default = |
| new(ctx) ir_variable(glsl_type::bool_type, |
| "run_default_tmp", |
| ir_var_temporary); |
| instructions->push_tail(state->switch_state.run_default); |
| |
| /* Loop around the switch is used for flow control. */ |
| ir_loop * loop = new(ctx) ir_loop(); |
| instructions->push_tail(loop); |
| |
| /* Cache test expression. |
| */ |
| test_to_hir(&loop->body_instructions, state); |
| |
| /* Emit code for body of switch stmt. |
| */ |
| body->hir(&loop->body_instructions, state); |
| |
| /* Insert a break at the end to exit loop. */ |
| ir_loop_jump *jump = new(ctx) ir_loop_jump(ir_loop_jump::jump_break); |
| loop->body_instructions.push_tail(jump); |
| |
| /* If we are inside loop, check if continue got called inside switch. */ |
| if (state->loop_nesting_ast != NULL) { |
| ir_dereference_variable *deref_continue_inside = |
| new(ctx) ir_dereference_variable(state->switch_state.continue_inside); |
| ir_if *irif = new(ctx) ir_if(deref_continue_inside); |
| ir_loop_jump *jump = new(ctx) ir_loop_jump(ir_loop_jump::jump_continue); |
| |
| if (state->loop_nesting_ast != NULL) { |
| if (state->loop_nesting_ast->rest_expression) { |
| state->loop_nesting_ast->rest_expression->hir(&irif->then_instructions, |
| state); |
| } |
| if (state->loop_nesting_ast->mode == |
| ast_iteration_statement::ast_do_while) { |
| state->loop_nesting_ast->condition_to_hir(&irif->then_instructions, state); |
| } |
| } |
| irif->then_instructions.push_tail(jump); |
| instructions->push_tail(irif); |
| } |
| |
| hash_table_dtor(state->switch_state.labels_ht); |
| |
| state->switch_state = saved; |
| |
| /* Switch statements do not have r-values. */ |
| return NULL; |
| } |
| |
| |
| void |
| ast_switch_statement::test_to_hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| void *ctx = state; |
| |
| /* Cache value of test expression. */ |
| ir_rvalue *const test_val = |
| test_expression->hir(instructions, |
| state); |
| |
| state->switch_state.test_var = new(ctx) ir_variable(test_val->type, |
| "switch_test_tmp", |
| ir_var_temporary); |
| ir_dereference_variable *deref_test_var = |
| new(ctx) ir_dereference_variable(state->switch_state.test_var); |
| |
| instructions->push_tail(state->switch_state.test_var); |
| instructions->push_tail(new(ctx) ir_assignment(deref_test_var, test_val)); |
| } |
| |
| |
| ir_rvalue * |
| ast_switch_body::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| if (stmts != NULL) |
| stmts->hir(instructions, state); |
| |
| /* Switch bodies do not have r-values. */ |
| return NULL; |
| } |
| |
| ir_rvalue * |
| ast_case_statement_list::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| exec_list default_case, after_default, tmp; |
| |
| foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases) { |
| case_stmt->hir(&tmp, state); |
| |
| /* Default case. */ |
| if (state->switch_state.previous_default && default_case.is_empty()) { |
| default_case.append_list(&tmp); |
| continue; |
| } |
| |
| /* If default case found, append 'after_default' list. */ |
| if (!default_case.is_empty()) |
| after_default.append_list(&tmp); |
| else |
| instructions->append_list(&tmp); |
| } |
| |
| /* Handle the default case. This is done here because default might not be |
| * the last case. We need to add checks against following cases first to see |
| * if default should be chosen or not. |
| */ |
| if (!default_case.is_empty()) { |
| |
| ir_rvalue *const true_val = new (state) ir_constant(true); |
| ir_dereference_variable *deref_run_default_var = |
| new(state) ir_dereference_variable(state->switch_state.run_default); |
| |
| /* Choose to run default case initially, following conditional |
| * assignments might change this. |
| */ |
| ir_assignment *const init_var = |
| new(state) ir_assignment(deref_run_default_var, true_val); |
| instructions->push_tail(init_var); |
| |
| /* Default case was the last one, no checks required. */ |
| if (after_default.is_empty()) { |
| instructions->append_list(&default_case); |
| return NULL; |
| } |
| |
| foreach_in_list(ir_instruction, ir, &after_default) { |
| ir_assignment *assign = ir->as_assignment(); |
| |
| if (!assign) |
| continue; |
| |
| /* Clone the check between case label and init expression. */ |
| ir_expression *exp = (ir_expression*) assign->condition; |
| ir_expression *clone = exp->clone(state, NULL); |
| |
| ir_dereference_variable *deref_var = |
| new(state) ir_dereference_variable(state->switch_state.run_default); |
| ir_rvalue *const false_val = new (state) ir_constant(false); |
| |
| ir_assignment *const set_false = |
| new(state) ir_assignment(deref_var, false_val, clone); |
| |
| instructions->push_tail(set_false); |
| } |
| |
| /* Append default case and all cases after it. */ |
| instructions->append_list(&default_case); |
| instructions->append_list(&after_default); |
| } |
| |
| /* Case statements do not have r-values. */ |
| return NULL; |
| } |
| |
| ir_rvalue * |
| ast_case_statement::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| labels->hir(instructions, state); |
| |
| /* Guard case statements depending on fallthru state. */ |
| ir_dereference_variable *const deref_fallthru_guard = |
| new(state) ir_dereference_variable(state->switch_state.is_fallthru_var); |
| ir_if *const test_fallthru = new(state) ir_if(deref_fallthru_guard); |
| |
| foreach_list_typed (ast_node, stmt, link, & this->stmts) |
| stmt->hir(& test_fallthru->then_instructions, state); |
| |
| instructions->push_tail(test_fallthru); |
| |
| /* Case statements do not have r-values. */ |
| return NULL; |
| } |
| |
| |
| ir_rvalue * |
| ast_case_label_list::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| foreach_list_typed (ast_case_label, label, link, & this->labels) |
| label->hir(instructions, state); |
| |
| /* Case labels do not have r-values. */ |
| return NULL; |
| } |
| |
| ir_rvalue * |
| ast_case_label::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| void *ctx = state; |
| |
| ir_dereference_variable *deref_fallthru_var = |
| new(ctx) ir_dereference_variable(state->switch_state.is_fallthru_var); |
| |
| ir_rvalue *const true_val = new(ctx) ir_constant(true); |
| |
| /* If not default case, ... */ |
| if (this->test_value != NULL) { |
| /* Conditionally set fallthru state based on |
| * comparison of cached test expression value to case label. |
| */ |
| ir_rvalue *const label_rval = this->test_value->hir(instructions, state); |
| ir_constant *label_const = label_rval->constant_expression_value(); |
| |
| if (!label_const) { |
| YYLTYPE loc = this->test_value->get_location(); |
| |
| _mesa_glsl_error(& loc, state, |
| "switch statement case label must be a " |
| "constant expression"); |
| |
| /* Stuff a dummy value in to allow processing to continue. */ |
| label_const = new(ctx) ir_constant(0); |
| } else { |
| ast_expression *previous_label = (ast_expression *) |
| hash_table_find(state->switch_state.labels_ht, |
| (void *)(uintptr_t)label_const->value.u[0]); |
| |
| if (previous_label) { |
| YYLTYPE loc = this->test_value->get_location(); |
| _mesa_glsl_error(& loc, state, "duplicate case value"); |
| |
| loc = previous_label->get_location(); |
| _mesa_glsl_error(& loc, state, "this is the previous case label"); |
| } else { |
| hash_table_insert(state->switch_state.labels_ht, |
| this->test_value, |
| (void *)(uintptr_t)label_const->value.u[0]); |
| } |
| } |
| |
| ir_dereference_variable *deref_test_var = |
| new(ctx) ir_dereference_variable(state->switch_state.test_var); |
| |
| ir_expression *test_cond = new(ctx) ir_expression(ir_binop_all_equal, |
| label_const, |
| deref_test_var); |
| |
| /* |
| * From GLSL 4.40 specification section 6.2 ("Selection"): |
| * |
| * "The type of the init-expression value in a switch statement must |
| * be a scalar int or uint. The type of the constant-expression value |
| * in a case label also must be a scalar int or uint. When any pair |
| * of these values is tested for "equal value" and the types do not |
| * match, an implicit conversion will be done to convert the int to a |
| * uint (see section 4.1.10 “Implicit Conversions”) before the compare |
| * is done." |
| */ |
| if (label_const->type != state->switch_state.test_var->type) { |
| YYLTYPE loc = this->test_value->get_location(); |
| |
| const glsl_type *type_a = label_const->type; |
| const glsl_type *type_b = state->switch_state.test_var->type; |
| |
| /* Check if int->uint implicit conversion is supported. */ |
| bool integer_conversion_supported = |
| glsl_type::int_type->can_implicitly_convert_to(glsl_type::uint_type, |
| state); |
| |
| if ((!type_a->is_integer() || !type_b->is_integer()) || |
| !integer_conversion_supported) { |
| _mesa_glsl_error(&loc, state, "type mismatch with switch " |
| "init-expression and case label (%s != %s)", |
| type_a->name, type_b->name); |
| } else { |
| /* Conversion of the case label. */ |
| if (type_a->base_type == GLSL_TYPE_INT) { |
| if (!apply_implicit_conversion(glsl_type::uint_type, |
| test_cond->operands[0], state)) |
| _mesa_glsl_error(&loc, state, "implicit type conversion error"); |
| } else { |
| /* Conversion of the init-expression value. */ |
| if (!apply_implicit_conversion(glsl_type::uint_type, |
| test_cond->operands[1], state)) |
| _mesa_glsl_error(&loc, state, "implicit type conversion error"); |
| } |
| } |
| } |
| |
| ir_assignment *set_fallthru_on_test = |
| new(ctx) ir_assignment(deref_fallthru_var, true_val, test_cond); |
| |
| instructions->push_tail(set_fallthru_on_test); |
| } else { /* default case */ |
| if (state->switch_state.previous_default) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(& loc, state, |
| "multiple default labels in one switch"); |
| |
| loc = state->switch_state.previous_default->get_location(); |
| _mesa_glsl_error(& loc, state, "this is the first default label"); |
| } |
| state->switch_state.previous_default = this; |
| |
| /* Set fallthru condition on 'run_default' bool. */ |
| ir_dereference_variable *deref_run_default = |
| new(ctx) ir_dereference_variable(state->switch_state.run_default); |
| ir_rvalue *const cond_true = new(ctx) ir_constant(true); |
| ir_expression *test_cond = new(ctx) ir_expression(ir_binop_all_equal, |
| cond_true, |
| deref_run_default); |
| |
| /* Set falltrhu state. */ |
| ir_assignment *set_fallthru = |
| new(ctx) ir_assignment(deref_fallthru_var, true_val, test_cond); |
| |
| instructions->push_tail(set_fallthru); |
| } |
| |
| /* Case statements do not have r-values. */ |
| return NULL; |
| } |
| |
| void |
| ast_iteration_statement::condition_to_hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| void *ctx = state; |
| |
| if (condition != NULL) { |
| ir_rvalue *const cond = |
| condition->hir(instructions, state); |
| |
| if ((cond == NULL) |
| || !cond->type->is_boolean() || !cond->type->is_scalar()) { |
| YYLTYPE loc = condition->get_location(); |
| |
| _mesa_glsl_error(& loc, state, |
| "loop condition must be scalar boolean"); |
| } else { |
| /* As the first code in the loop body, generate a block that looks |
| * like 'if (!condition) break;' as the loop termination condition. |
| */ |
| ir_rvalue *const not_cond = |
| new(ctx) ir_expression(ir_unop_logic_not, cond); |
| |
| ir_if *const if_stmt = new(ctx) ir_if(not_cond); |
| |
| ir_jump *const break_stmt = |
| new(ctx) ir_loop_jump(ir_loop_jump::jump_break); |
| |
| if_stmt->then_instructions.push_tail(break_stmt); |
| instructions->push_tail(if_stmt); |
| } |
| } |
| } |
| |
| |
| ir_rvalue * |
| ast_iteration_statement::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| void *ctx = state; |
| |
| /* For-loops and while-loops start a new scope, but do-while loops do not. |
| */ |
| if (mode != ast_do_while) |
| state->symbols->push_scope(); |
| |
| if (init_statement != NULL) |
| init_statement->hir(instructions, state); |
| |
| ir_loop *const stmt = new(ctx) ir_loop(); |
| instructions->push_tail(stmt); |
| |
| /* Track the current loop nesting. */ |
| ast_iteration_statement *nesting_ast = state->loop_nesting_ast; |
| |
| state->loop_nesting_ast = this; |
| |
| /* Likewise, indicate that following code is closest to a loop, |
| * NOT closest to a switch. |
| */ |
| bool saved_is_switch_innermost = state->switch_state.is_switch_innermost; |
| state->switch_state.is_switch_innermost = false; |
| |
| if (mode != ast_do_while) |
| condition_to_hir(&stmt->body_instructions, state); |
| |
| if (body != NULL) |
| body->hir(& stmt->body_instructions, state); |
| |
| if (rest_expression != NULL) |
| rest_expression->hir(& stmt->body_instructions, state); |
| |
| if (mode == ast_do_while) |
| condition_to_hir(&stmt->body_instructions, state); |
| |
| if (mode != ast_do_while) |
| state->symbols->pop_scope(); |
| |
| /* Restore previous nesting before returning. */ |
| state->loop_nesting_ast = nesting_ast; |
| state->switch_state.is_switch_innermost = saved_is_switch_innermost; |
| |
| /* Loops do not have r-values. |
| */ |
| return NULL; |
| } |
| |
| |
| /** |
| * Determine if the given type is valid for establishing a default precision |
| * qualifier. |
| * |
| * From GLSL ES 3.00 section 4.5.4 ("Default Precision Qualifiers"): |
| * |
| * "The precision statement |
| * |
| * precision precision-qualifier type; |
| * |
| * can be used to establish a default precision qualifier. The type field |
| * can be either int or float or any of the sampler types, and the |
| * precision-qualifier can be lowp, mediump, or highp." |
| * |
| * GLSL ES 1.00 has similar language. GLSL 1.30 doesn't allow precision |
| * qualifiers on sampler types, but this seems like an oversight (since the |
| * intention of including these in GLSL 1.30 is to allow compatibility with ES |
| * shaders). So we allow int, float, and all sampler types regardless of GLSL |
| * version. |
| */ |
| static bool |
| is_valid_default_precision_type(const struct glsl_type *const type) |
| { |
| if (type == NULL) |
| return false; |
| |
| switch (type->base_type) { |
| case GLSL_TYPE_INT: |
| case GLSL_TYPE_FLOAT: |
| /* "int" and "float" are valid, but vectors and matrices are not. */ |
| return type->vector_elements == 1 && type->matrix_columns == 1; |
| case GLSL_TYPE_SAMPLER: |
| case GLSL_TYPE_IMAGE: |
| case GLSL_TYPE_ATOMIC_UINT: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| |
| ir_rvalue * |
| ast_type_specifier::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| if (this->default_precision == ast_precision_none && this->structure == NULL) |
| return NULL; |
| |
| YYLTYPE loc = this->get_location(); |
| |
| /* If this is a precision statement, check that the type to which it is |
| * applied is either float or int. |
| * |
| * From section 4.5.3 of the GLSL 1.30 spec: |
| * "The precision statement |
| * precision precision-qualifier type; |
| * can be used to establish a default precision qualifier. The type |
| * field can be either int or float [...]. Any other types or |
| * qualifiers will result in an error. |
| */ |
| if (this->default_precision != ast_precision_none) { |
| if (!state->check_precision_qualifiers_allowed(&loc)) |
| return NULL; |
| |
| if (this->structure != NULL) { |
| _mesa_glsl_error(&loc, state, |
| "precision qualifiers do not apply to structures"); |
| return NULL; |
| } |
| |
| if (this->array_specifier != NULL) { |
| _mesa_glsl_error(&loc, state, |
| "default precision statements do not apply to " |
| "arrays"); |
| return NULL; |
| } |
| |
| const struct glsl_type *const type = |
| state->symbols->get_type(this->type_name); |
| if (!is_valid_default_precision_type(type)) { |
| _mesa_glsl_error(&loc, state, |
| "default precision statements apply only to " |
| "float, int, and opaque types"); |
| return NULL; |
| } |
| |
| if (type->base_type == GLSL_TYPE_FLOAT |
| && state->es_shader |
| && state->stage == MESA_SHADER_FRAGMENT) { |
| /* Section 4.5.3 (Default Precision Qualifiers) of the GLSL ES 1.00 |
| * spec says: |
| * |
| * "The fragment language has no default precision qualifier for |
| * floating point types." |
| * |
| * As a result, we have to track whether or not default precision has |
| * been specified for float in GLSL ES fragment shaders. |
| * |
| * Earlier in that same section, the spec says: |
| * |
| * "Non-precision qualified declarations will use the precision |
| * qualifier specified in the most recent precision statement |
| * that is still in scope. The precision statement has the same |
| * scoping rules as variable declarations. If it is declared |
| * inside a compound statement, its effect stops at the end of |
| * the innermost statement it was declared in. Precision |
| * statements in nested scopes override precision statements in |
| * outer scopes. Multiple precision statements for the same basic |
| * type can appear inside the same scope, with later statements |
| * overriding earlier statements within that scope." |
| * |
| * Default precision specifications follow the same scope rules as |
| * variables. So, we can track the state of the default float |
| * precision in the symbol table, and the rules will just work. This |
| * is a slight abuse of the symbol table, but it has the semantics |
| * that we want. |
| */ |
| ir_variable *const junk = |
| new(state) ir_variable(type, "#default precision", |
| ir_var_auto); |
| |
| state->symbols->add_variable(junk); |
| } |
| |
| /* FINISHME: Translate precision statements into IR. */ |
| return NULL; |
| } |
| |
| /* _mesa_ast_set_aggregate_type() sets the <structure> field so that |
| * process_record_constructor() can do type-checking on C-style initializer |
| * expressions of structs, but ast_struct_specifier should only be translated |
| * to HIR if it is declaring the type of a structure. |
| * |
| * The ->is_declaration field is false for initializers of variables |
| * declared separately from the struct's type definition. |
| * |
| * struct S { ... }; (is_declaration = true) |
| * struct T { ... } t = { ... }; (is_declaration = true) |
| * S s = { ... }; (is_declaration = false) |
| */ |
| if (this->structure != NULL && this->structure->is_declaration) |
| return this->structure->hir(instructions, state); |
| |
| return NULL; |
| } |
| |
| |
| /** |
| * Process a structure or interface block tree into an array of structure fields |
| * |
| * After parsing, where there are some syntax differnces, structures and |
| * interface blocks are almost identical. They are similar enough that the |
| * AST for each can be processed the same way into a set of |
| * \c glsl_struct_field to describe the members. |
| * |
| * If we're processing an interface block, var_mode should be the type of the |
| * interface block (ir_var_shader_in, ir_var_shader_out, ir_var_uniform or |
| * ir_var_shader_storage). If we're processing a structure, var_mode should be |
| * ir_var_auto. |
| * |
| * \return |
| * The number of fields processed. A pointer to the array structure fields is |
| * stored in \c *fields_ret. |
| */ |
| unsigned |
| ast_process_structure_or_interface_block(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state, |
| exec_list *declarations, |
| YYLTYPE &loc, |
| glsl_struct_field **fields_ret, |
| bool is_interface, |
| enum glsl_matrix_layout matrix_layout, |
| bool allow_reserved_names, |
| ir_variable_mode var_mode, |
| ast_type_qualifier *layout) |
| { |
| unsigned decl_count = 0; |
| |
| /* For blocks that accept memory qualifiers (i.e. shader storage), verify |
| * that we don't have incompatible qualifiers |
| */ |
| if (layout && layout->flags.q.read_only && layout->flags.q.write_only) { |
| _mesa_glsl_error(&loc, state, |
| "Interface block sets both readonly and writeonly"); |
| } |
| |
| /* Make an initial pass over the list of fields to determine how |
| * many there are. Each element in this list is an ast_declarator_list. |
| * This means that we actually need to count the number of elements in the |
| * 'declarations' list in each of the elements. |
| */ |
| foreach_list_typed (ast_declarator_list, decl_list, link, declarations) { |
| decl_count += decl_list->declarations.length(); |
| } |
| |
| /* Allocate storage for the fields and process the field |
| * declarations. As the declarations are processed, try to also convert |
| * the types to HIR. This ensures that structure definitions embedded in |
| * other structure definitions or in interface blocks are processed. |
| */ |
| glsl_struct_field *const fields = ralloc_array(state, glsl_struct_field, |
| decl_count); |
| |
| unsigned i = 0; |
| foreach_list_typed (ast_declarator_list, decl_list, link, declarations) { |
| const char *type_name; |
| |
| decl_list->type->specifier->hir(instructions, state); |
| |
| /* Section 10.9 of the GLSL ES 1.00 specification states that |
| * embedded structure definitions have been removed from the language. |
| */ |
| if (state->es_shader && decl_list->type->specifier->structure != NULL) { |
| _mesa_glsl_error(&loc, state, "embedded structure definitions are " |
| "not allowed in GLSL ES 1.00"); |
| } |
| |
| const glsl_type *decl_type = |
| decl_list->type->glsl_type(& type_name, state); |
| |
| foreach_list_typed (ast_declaration, decl, link, |
| &decl_list->declarations) { |
| if (!allow_reserved_names) |
| validate_identifier(decl->identifier, loc, state); |
| |
| /* From section 4.3.9 of the GLSL 4.40 spec: |
| * |
| * "[In interface blocks] opaque types are not allowed." |
| * |
| * It should be impossible for decl_type to be NULL here. Cases that |
| * might naturally lead to decl_type being NULL, especially for the |
| * is_interface case, will have resulted in compilation having |
| * already halted due to a syntax error. |
| */ |
| const struct glsl_type *field_type = |
| decl_type != NULL ? decl_type : glsl_type::error_type; |
| |
| if (is_interface && field_type->contains_opaque()) { |
| YYLTYPE loc = decl_list->get_location(); |
| _mesa_glsl_error(&loc, state, |
| "uniform/buffer in non-default interface block contains " |
| "opaque variable"); |
| } |
| |
| if (field_type->contains_atomic()) { |
| /* From section 4.1.7.3 of the GLSL 4.40 spec: |
| * |
| * "Members of structures cannot be declared as atomic counter |
| * types." |
| */ |
| YYLTYPE loc = decl_list->get_location(); |
| _mesa_glsl_error(&loc, state, "atomic counter in structure, " |
| "shader storage block or uniform block"); |
| } |
| |
| if (field_type->contains_image()) { |
| /* FINISHME: Same problem as with atomic counters. |
| * FINISHME: Request clarification from Khronos and add |
| * FINISHME: spec quotation here. |
| */ |
| YYLTYPE loc = decl_list->get_location(); |
| _mesa_glsl_error(&loc, state, |
| "image in structure, shader storage block or " |
| "uniform block"); |
| } |
| |
| const struct ast_type_qualifier *const qual = |
| & decl_list->type->qualifier; |
| if (qual->flags.q.std140 || |
| qual->flags.q.std430 || |
| qual->flags.q.packed || |
| qual->flags.q.shared) { |
| _mesa_glsl_error(&loc, state, |
| "uniform/shader storage block layout qualifiers " |
| "std140, std430, packed, and shared can only be " |
| "applied to uniform/shader storage blocks, not " |
| "members"); |
| } |
| |
| if (qual->flags.q.constant) { |
| YYLTYPE loc = decl_list->get_location(); |
| _mesa_glsl_error(&loc, state, |
| "const storage qualifier cannot be applied " |
| "to struct or interface block members"); |
| } |
| |
| field_type = process_array_type(&loc, decl_type, |
| decl->array_specifier, state); |
| fields[i].type = field_type; |
| fields[i].name = decl->identifier; |
| fields[i].location = -1; |
| fields[i].interpolation = |
| interpret_interpolation_qualifier(qual, var_mode, state, &loc); |
| fields[i].centroid = qual->flags.q.centroid ? 1 : 0; |
| fields[i].sample = qual->flags.q.sample ? 1 : 0; |
| fields[i].patch = qual->flags.q.patch ? 1 : 0; |
| |
| /* Only save explicitly defined streams in block's field */ |
| fields[i].stream = qual->flags.q.explicit_stream ? qual->stream : -1; |
| |
| if (qual->flags.q.row_major || qual->flags.q.column_major) { |
| if (!qual->flags.q.uniform && !qual->flags.q.buffer) { |
| _mesa_glsl_error(&loc, state, |
| "row_major and column_major can only be " |
| "applied to interface blocks"); |
| } else |
| validate_matrix_layout_for_type(state, &loc, field_type, NULL); |
| } |
| |
| if (qual->flags.q.uniform && qual->has_interpolation()) { |
| _mesa_glsl_error(&loc, state, |
| "interpolation qualifiers cannot be used " |
| "with uniform interface blocks"); |
| } |
| |
| if ((qual->flags.q.uniform || !is_interface) && |
| qual->has_auxiliary_storage()) { |
| _mesa_glsl_error(&loc, state, |
| "auxiliary storage qualifiers cannot be used " |
| "in uniform blocks or structures."); |
| } |
| |
| /* Propogate row- / column-major information down the fields of the |
| * structure or interface block. Structures need this data because |
| * the structure may contain a structure that contains ... a matrix |
| * that need the proper layout. |
| */ |
| if (field_type->without_array()->is_matrix() |
| || field_type->without_array()->is_record()) { |
| /* If no layout is specified for the field, inherit the layout |
| * from the block. |
| */ |
| fields[i].matrix_layout = matrix_layout; |
| |
| if (qual->flags.q.row_major) |
| fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_ROW_MAJOR; |
| else if (qual->flags.q.column_major) |
| fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR; |
| |
| /* If we're processing an interface block, the matrix layout must |
| * be decided by this point. |
| */ |
| assert(!is_interface |
| || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR |
| || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR); |
| } |
| |
| /* Image qualifiers are allowed on buffer variables, which can only |
| * be defined inside shader storage buffer objects |
| */ |
| if (layout && var_mode == ir_var_shader_storage) { |
| if (qual->flags.q.read_only && qual->flags.q.write_only) { |
| _mesa_glsl_error(&loc, state, |
| "buffer variable `%s' can't be " |
| "readonly and writeonly.", fields[i].name); |
| } |
| |
| /* For readonly and writeonly qualifiers the field definition, |
| * if set, overwrites the layout qualifier. |
| */ |
| bool read_only = layout->flags.q.read_only; |
| bool write_only = layout->flags.q.write_only; |
| |
| if (qual->flags.q.read_only) { |
| read_only = true; |
| write_only = false; |
| } else if (qual->flags.q.write_only) { |
| read_only = false; |
| write_only = true; |
| } |
| |
| fields[i].image_read_only = read_only; |
| fields[i].image_write_only = write_only; |
| |
| /* For other qualifiers, we set the flag if either the layout |
| * qualifier or the field qualifier are set |
| */ |
| fields[i].image_coherent = qual->flags.q.coherent || |
| layout->flags.q.coherent; |
| fields[i].image_volatile = qual->flags.q._volatile || |
| layout->flags.q._volatile; |
| fields[i].image_restrict = qual->flags.q.restrict_flag || |
| layout->flags.q.restrict_flag; |
| } |
| |
| i++; |
| } |
| } |
| |
| assert(i == decl_count); |
| |
| *fields_ret = fields; |
| return decl_count; |
| } |
| |
| |
| ir_rvalue * |
| ast_struct_specifier::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| YYLTYPE loc = this->get_location(); |
| |
| /* Section 4.1.8 (Structures) of the GLSL 1.10 spec says: |
| * |
| * "Anonymous structures are not supported; so embedded structures must |
| * have a declarator. A name given to an embedded struct is scoped at |
| * the same level as the struct it is embedded in." |
| * |
| * The same section of the GLSL 1.20 spec says: |
| * |
| * "Anonymous structures are not supported. Embedded structures are not |
| * supported. |
| * |
| * struct S { float f; }; |
| * struct T { |
| * S; // Error: anonymous structures disallowed |
| * struct { ... }; // Error: embedded structures disallowed |
| * S s; // Okay: nested structures with name are allowed |
| * };" |
| * |
| * The GLSL ES 1.00 and 3.00 specs have similar langauge and examples. So, |
| * we allow embedded structures in 1.10 only. |
| */ |
| if (state->language_version != 110 && state->struct_specifier_depth != 0) |
| _mesa_glsl_error(&loc, state, |
| "embedded structure declarations are not allowed"); |
| |
| state->struct_specifier_depth++; |
| |
| glsl_struct_field *fields; |
| unsigned decl_count = |
| ast_process_structure_or_interface_block(instructions, |
| state, |
| &this->declarations, |
| loc, |
| &fields, |
| false, |
| GLSL_MATRIX_LAYOUT_INHERITED, |
| false /* allow_reserved_names */, |
| ir_var_auto, |
| NULL); |
| |
| validate_identifier(this->name, loc, state); |
| |
| const glsl_type *t = |
| glsl_type::get_record_instance(fields, decl_count, this->name); |
| |
| if (!state->symbols->add_type(name, t)) { |
| _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name); |
| } else { |
| const glsl_type **s = reralloc(state, state->user_structures, |
| const glsl_type *, |
| state->num_user_structures + 1); |
| if (s != NULL) { |
| s[state->num_user_structures] = t; |
| state->user_structures = s; |
| state->num_user_structures++; |
| } |
| } |
| |
| state->struct_specifier_depth--; |
| |
| /* Structure type definitions do not have r-values. |
| */ |
| return NULL; |
| } |
| |
| |
| /** |
| * Visitor class which detects whether a given interface block has been used. |
| */ |
| class interface_block_usage_visitor : public ir_hierarchical_visitor |
| { |
| public: |
| interface_block_usage_visitor(ir_variable_mode mode, const glsl_type *block) |
| : mode(mode), block(block), found(false) |
| { |
| } |
| |
| virtual ir_visitor_status visit(ir_dereference_variable *ir) |
| { |
| if (ir->var->data.mode == mode && ir->var->get_interface_type() == block) { |
| found = true; |
| return visit_stop; |
| } |
| return visit_continue; |
| } |
| |
| bool usage_found() const |
| { |
| return this->found; |
| } |
| |
| private: |
| ir_variable_mode mode; |
| const glsl_type *block; |
| bool found; |
| }; |
| |
| static bool |
| is_unsized_array_last_element(ir_variable *v) |
| { |
| const glsl_type *interface_type = v->get_interface_type(); |
| int length = interface_type->length; |
| |
| assert(v->type->is_unsized_array()); |
| |
| /* Check if it is the last element of the interface */ |
| if (strcmp(interface_type->fields.structure[length-1].name, v->name) == 0) |
| return true; |
| return false; |
| } |
| |
| ir_rvalue * |
| ast_interface_block::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| YYLTYPE loc = this->get_location(); |
| |
| /* Interface blocks must be declared at global scope */ |
| if (state->current_function != NULL) { |
| _mesa_glsl_error(&loc, state, |
| "Interface block `%s' must be declared " |
| "at global scope", |
| this->block_name); |
| } |
| |
| if (!this->layout.flags.q.buffer && |
| this->layout.flags.q.std430) { |
| _mesa_glsl_error(&loc, state, |
| "std430 storage block layout qualifier is supported " |
| "only for shader storage blocks"); |
| } |
| |
| /* The ast_interface_block has a list of ast_declarator_lists. We |
| * need to turn those into ir_variables with an association |
| * with this uniform block. |
| */ |
| enum glsl_interface_packing packing; |
| if (this->layout.flags.q.shared) { |
| packing = GLSL_INTERFACE_PACKING_SHARED; |
| } else if (this->layout.flags.q.packed) { |
| packing = GLSL_INTERFACE_PACKING_PACKED; |
| } else if (this->layout.flags.q.std430) { |
| packing = GLSL_INTERFACE_PACKING_STD430; |
| } else { |
| /* The default layout is std140. |
| */ |
| packing = GLSL_INTERFACE_PACKING_STD140; |
| } |
| |
| ir_variable_mode var_mode; |
| const char *iface_type_name; |
| if (this->layout.flags.q.in) { |
| var_mode = ir_var_shader_in; |
| iface_type_name = "in"; |
| } else if (this->layout.flags.q.out) { |
| var_mode = ir_var_shader_out; |
| iface_type_name = "out"; |
| } else if (this->layout.flags.q.uniform) { |
| var_mode = ir_var_uniform; |
| iface_type_name = "uniform"; |
| } else if (this->layout.flags.q.buffer) { |
| var_mode = ir_var_shader_storage; |
| iface_type_name = "buffer"; |
| } else { |
| var_mode = ir_var_auto; |
| iface_type_name = "UNKNOWN"; |
| assert(!"interface block layout qualifier not found!"); |
| } |
| |
| enum glsl_matrix_layout matrix_layout = GLSL_MATRIX_LAYOUT_INHERITED; |
| if (this->layout.flags.q.row_major) |
| matrix_layout = GLSL_MATRIX_LAYOUT_ROW_MAJOR; |
| else if (this->layout.flags.q.column_major) |
| matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR; |
| |
| bool redeclaring_per_vertex = strcmp(this->block_name, "gl_PerVertex") == 0; |
| exec_list declared_variables; |
| glsl_struct_field *fields; |
| |
| /* Treat an interface block as one level of nesting, so that embedded struct |
| * specifiers will be disallowed. |
| */ |
| state->struct_specifier_depth++; |
| |
| unsigned int num_variables = |
| ast_process_structure_or_interface_block(&declared_variables, |
| state, |
| &this->declarations, |
| loc, |
| &fields, |
| true, |
| matrix_layout, |
| redeclaring_per_vertex, |
| var_mode, |
| &this->layout); |
| |
| state->struct_specifier_depth--; |
| |
| if (!redeclaring_per_vertex) { |
| validate_identifier(this->block_name, loc, state); |
| |
| /* From section 4.3.9 ("Interface Blocks") of the GLSL 4.50 spec: |
| * |
| * "Block names have no other use within a shader beyond interface |
| * matching; it is a compile-time error to use a block name at global |
| * scope for anything other than as a block name." |
| */ |
| ir_variable *var = state->symbols->get_variable(this->block_name); |
| if (var && !var->type->is_interface()) { |
| _mesa_glsl_error(&loc, state, "Block name `%s' is " |
| "already used in the scope.", |
| this->block_name); |
| } |
| } |
| |
| const glsl_type *earlier_per_vertex = NULL; |
| if (redeclaring_per_vertex) { |
| /* Find the previous declaration of gl_PerVertex. If we're redeclaring |
| * the named interface block gl_in, we can find it by looking at the |
| * previous declaration of gl_in. Otherwise we can find it by looking |
| * at the previous decalartion of any of the built-in outputs, |
| * e.g. gl_Position. |
| * |
| * Also check that the instance name and array-ness of the redeclaration |
| * are correct. |
| */ |
| switch (var_mode) { |
| case ir_var_shader_in: |
| if (ir_variable *earlier_gl_in = |
| state->symbols->get_variable("gl_in")) { |
| earlier_per_vertex = earlier_gl_in->get_interface_type(); |
| } else { |
| _mesa_glsl_error(&loc, state, |
| "redeclaration of gl_PerVertex input not allowed " |
| "in the %s shader", |
| _mesa_shader_stage_to_string(state->stage)); |
| } |
| if (this->instance_name == NULL || |
| strcmp(this->instance_name, "gl_in") != 0 || this->array_specifier == NULL) { |
| _mesa_glsl_error(&loc, state, |
| "gl_PerVertex input must be redeclared as " |
| "gl_in[]"); |
| } |
| break; |
| case ir_var_shader_out: |
| if (ir_variable *earlier_gl_Position = |
| state->symbols->get_variable("gl_Position")) { |
| earlier_per_vertex = earlier_gl_Position->get_interface_type(); |
| } else if (ir_variable *earlier_gl_out = |
| state->symbols->get_variable("gl_out")) { |
| earlier_per_vertex = earlier_gl_out->get_interface_type(); |
| } else { |
| _mesa_glsl_error(&loc, state, |
| "redeclaration of gl_PerVertex output not " |
| "allowed in the %s shader", |
| _mesa_shader_stage_to_string(state->stage)); |
| } |
| if (state->stage == MESA_SHADER_TESS_CTRL) { |
| if (this->instance_name == NULL || |
| strcmp(this->instance_name, "gl_out") != 0 || this->array_specifier == NULL) { |
| _mesa_glsl_error(&loc, state, |
| "gl_PerVertex output must be redeclared as " |
| "gl_out[]"); |
| } |
| } else { |
| if (this->instance_name != NULL) { |
| _mesa_glsl_error(&loc, state, |
| "gl_PerVertex output may not be redeclared with " |
| "an instance name"); |
| } |
| } |
| break; |
| default: |
| _mesa_glsl_error(&loc, state, |
| "gl_PerVertex must be declared as an input or an " |
| "output"); |
| break; |
| } |
| |
| if (earlier_per_vertex == NULL) { |
| /* An error has already been reported. Bail out to avoid null |
| * dereferences later in this function. |
| */ |
| return NULL; |
| } |
| |
| /* Copy locations from the old gl_PerVertex interface block. */ |
| for (unsigned i = 0; i < num_variables; i++) { |
| int j = earlier_per_vertex->field_index(fields[i].name); |
| if (j == -1) { |
| _mesa_glsl_error(&loc, state, |
| "redeclaration of gl_PerVertex must be a subset " |
| "of the built-in members of gl_PerVertex"); |
| } else { |
| fields[i].location = |
| earlier_per_vertex->fields.structure[j].location; |
| fields[i].interpolation = |
| earlier_per_vertex->fields.structure[j].interpolation; |
| fields[i].centroid = |
| earlier_per_vertex->fields.structure[j].centroid; |
| fields[i].sample = |
| earlier_per_vertex->fields.structure[j].sample; |
| fields[i].patch = |
| earlier_per_vertex->fields.structure[j].patch; |
| } |
| } |
| |
| /* From section 7.1 ("Built-in Language Variables") of the GLSL 4.10 |
| * spec: |
| * |
| * If a built-in interface block is redeclared, it must appear in |
| * the shader before any use of any member included in the built-in |
| * declaration, or a compilation error will result. |
| * |
| * This appears to be a clarification to the behaviour established for |
| * gl_PerVertex by GLSL 1.50, therefore we implement this behaviour |
| * regardless of GLSL version. |
| */ |
| interface_block_usage_visitor v(var_mode, earlier_per_vertex); |
| v.run(instructions); |
| if (v.usage_found()) { |
| _mesa_glsl_error(&loc, state, |
| "redeclaration of a built-in interface block must " |
| "appear before any use of any member of the " |
| "interface block"); |
| } |
| } |
| |
| const glsl_type *block_type = |
| glsl_type::get_interface_instance(fields, |
| num_variables, |
| packing, |
| this->block_name); |
| if (this->layout.flags.q.explicit_binding) |
| validate_binding_qualifier(state, &loc, block_type, &this->layout); |
| |
| if (!state->symbols->add_interface(block_type->name, block_type, var_mode)) { |
| YYLTYPE loc = this->get_location(); |
| _mesa_glsl_error(&loc, state, "interface block `%s' with type `%s' " |
| "already taken in the current scope", |
| this->block_name, iface_type_name); |
| } |
| |
| /* Since interface blocks cannot contain statements, it should be |
| * impossible for the block to generate any instructions. |
| */ |
| assert(declared_variables.is_empty()); |
| |
| /* From section 4.3.4 (Inputs) of the GLSL 1.50 spec: |
| * |
| * Geometry shader input variables get the per-vertex values written |
| * out by vertex shader output variables of the same names. Since a |
| * geometry shader operates on a set of vertices, each input varying |
| * variable (or input block, see interface blocks below) needs to be |
| * declared as an array. |
| */ |
| if (state->stage == MESA_SHADER_GEOMETRY && this->array_specifier == NULL && |
| var_mode == ir_var_shader_in) { |
| _mesa_glsl_error(&loc, state, "geometry shader inputs must be arrays"); |
| } else if ((state->stage == MESA_SHADER_TESS_CTRL || |
| state->stage == MESA_SHADER_TESS_EVAL) && |
| this->array_specifier == NULL && |
| var_mode == ir_var_shader_in) { |
| _mesa_glsl_error(&loc, state, "per-vertex tessellation shader inputs must be arrays"); |
| } else if (state->stage == MESA_SHADER_TESS_CTRL && |
| this->array_specifier == NULL && |
| var_mode == ir_var_shader_out) { |
| _mesa_glsl_error(&loc, state, "tessellation control shader outputs must be arrays"); |
| } |
| |
| |
| /* Page 39 (page 45 of the PDF) of section 4.3.7 in the GLSL ES 3.00 spec |
| * says: |
| * |
| * "If an instance name (instance-name) is used, then it puts all the |
| * members inside a scope within its own name space, accessed with the |
| * field selector ( . ) operator (analogously to structures)." |
| */ |
| if (this->instance_name) { |
| if (redeclaring_per_vertex) { |
| /* When a built-in in an unnamed interface block is redeclared, |
| * get_variable_being_redeclared() calls |
| * check_builtin_array_max_size() to make sure that built-in array |
| * variables aren't redeclared to illegal sizes. But we're looking |
| * at a redeclaration of a named built-in interface block. So we |
| * have to manually call check_builtin_array_max_size() for all parts |
| * of the interface that are arrays. |
| */ |
| for (unsigned i = 0; i < num_variables; i++) { |
| if (fields[i].type->is_array()) { |
| const unsigned size = fields[i].type->array_size(); |
| check_builtin_array_max_size(fields[i].name, size, loc, state); |
| } |
| } |
| } else { |
| validate_identifier(this->instance_name, loc, state); |
| } |
| |
| ir_variable *var; |
| |
| if (this->array_specifier != NULL) { |
| /* Section 4.3.7 (Interface Blocks) of the GLSL 1.50 spec says: |
| * |
| * For uniform blocks declared an array, each individual array |
| * element corresponds to a separate buffer object backing one |
| * instance of the block. As the array size indicates the number |
| * of buffer objects needed, uniform block array declarations |
| * must specify an array size. |
| * |
| * And a few paragraphs later: |
| * |
| * Geometry shader input blocks must be declared as arrays and |
| * follow the array declaration and linking rules for all |
| * geometry shader inputs. All other input and output block |
| * arrays must specify an array size. |
| * |
| * The same applies to tessellation shaders. |
| * |
| * The upshot of this is that the only circumstance where an |
| * interface array size *doesn't* need to be specified is on a |
| * geometry shader input, tessellation control shader input, |
| * tessellation control shader output, and tessellation evaluation |
| * shader input. |
| */ |
| if (this->array_specifier->is_unsized_array) { |
| bool allow_inputs = state->stage == MESA_SHADER_GEOMETRY || |
| state->stage == MESA_SHADER_TESS_CTRL || |
| state->stage == MESA_SHADER_TESS_EVAL; |
| bool allow_outputs = state->stage == MESA_SHADER_TESS_CTRL; |
| |
| if (this->layout.flags.q.in) { |
| if (!allow_inputs) |
| _mesa_glsl_error(&loc, state, |
| "unsized input block arrays not allowed in " |
| "%s shader", |
| _mesa_shader_stage_to_string(state->stage)); |
| } else if (this->layout.flags.q.out) { |
| if (!allow_outputs) |
| _mesa_glsl_error(&loc, state, |
| "unsized output block arrays not allowed in " |
| "%s shader", |
| _mesa_shader_stage_to_string(state->stage)); |
| } else { |
| /* by elimination, this is a uniform block array */ |
| _mesa_glsl_error(&loc, state, |
| "unsized uniform block arrays not allowed in " |
| "%s shader", |
| _mesa_shader_stage_to_string(state->stage)); |
| } |
| } |
| |
| const glsl_type *block_array_type = |
| process_array_type(&loc, block_type, this->array_specifier, state); |
| |
| /* From section 4.3.9 (Interface Blocks) of the GLSL ES 3.10 spec: |
| * |
| * * Arrays of arrays of blocks are not allowed |
| */ |
| if (state->es_shader && block_array_type->is_array() && |
| block_array_type->fields.array->is_array()) { |
| _mesa_glsl_error(&loc, state, |
| "arrays of arrays interface blocks are " |
| "not allowed"); |
| } |
| |
| if (this->layout.flags.q.explicit_binding) |
| validate_binding_qualifier(state, &loc, block_array_type, |
| &this->layout); |
| |
| var = new(state) ir_variable(block_array_type, |
| this->instance_name, |
| var_mode); |
| } else { |
| var = new(state) ir_variable(block_type, |
| this->instance_name, |
| var_mode); |
| } |
| |
| var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED |
| ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout; |
| |
| if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform) |
| var->data.read_only = true; |
| |
| if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in) |
| handle_geometry_shader_input_decl(state, loc, var); |
| else if ((state->stage == MESA_SHADER_TESS_CTRL || |
| state->stage == MESA_SHADER_TESS_EVAL) && var_mode == ir_var_shader_in) |
| handle_tess_shader_input_decl(state, loc, var); |
| else if (state->stage == MESA_SHADER_TESS_CTRL && var_mode == ir_var_shader_out) |
| handle_tess_ctrl_shader_output_decl(state, loc, var); |
| |
| for (unsigned i = 0; i < num_variables; i++) { |
| if (fields[i].type->is_unsized_array()) { |
| if (var_mode == ir_var_shader_storage) { |
| if (i != (num_variables - 1)) { |
| _mesa_glsl_error(&loc, state, "unsized array `%s' definition: " |
| "only last member of a shader storage block " |
| "can be defined as unsized array", |
| fields[i].name); |
| } |
| } else { |
| /* From GLSL ES 3.10 spec, section 4.1.9 "Arrays": |
| * |
| * "If an array is declared as the last member of a shader storage |
| * block and the size is not specified at compile-time, it is |
| * sized at run-time. In all other cases, arrays are sized only |
| * at compile-time." |
| */ |
| if (state->es_shader) { |
| _mesa_glsl_error(&loc, state, "unsized array `%s' definition: " |
| "only last member of a shader storage block " |
| "can be defined as unsized array", |
| fields[i].name); |
| } |
| } |
| } |
| } |
| |
| if (ir_variable *earlier = |
| state->symbols->get_variable(this->instance_name)) { |
| if (!redeclaring_per_vertex) { |
| _mesa_glsl_error(&loc, state, "`%s' redeclared", |
| this->instance_name); |
| } |
| earlier->data.how_declared = ir_var_declared_normally; |
| earlier->type = var->type; |
| earlier->reinit_interface_type(block_type); |
| delete var; |
| } else { |
| /* Propagate the "binding" keyword into this UBO's fields; |
| * the UBO declaration itself doesn't get an ir_variable unless it |
| * has an instance name. This is ugly. |
| */ |
| var->data.explicit_binding = this->layout.flags.q.explicit_binding; |
| var->data.binding = this->layout.binding; |
| |
| state->symbols->add_variable(var); |
| instructions->push_tail(var); |
| } |
| } else { |
| /* In order to have an array size, the block must also be declared with |
| * an instance name. |
| */ |
| assert(this->array_specifier == NULL); |
| |
| for (unsigned i = 0; i < num_variables; i++) { |
| ir_variable *var = |
| new(state) ir_variable(fields[i].type, |
| ralloc_strdup(state, fields[i].name), |
| var_mode); |
| var->data.interpolation = fields[i].interpolation; |
| var->data.centroid = fields[i].centroid; |
| var->data.sample = fields[i].sample; |
| var->data.patch = fields[i].patch; |
| var->init_interface_type(block_type); |
| |
| if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform) |
| var->data.read_only = true; |
| |
| if (fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED) { |
| var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED |
| ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout; |
| } else { |
| var->data.matrix_layout = fields[i].matrix_layout; |
| } |
| |
| if (fields[i].stream != -1 && |
| ((unsigned)fields[i].stream) != this->layout.stream) { |
| _mesa_glsl_error(&loc, state, |
| "stream layout qualifier on " |
| "interface block member `%s' does not match " |
| "the interface block (%d vs %d)", |
| var->name, fields[i].stream, this->layout.stream); |
| } |
| |
| var->data.stream = this->layout.stream; |
| |
| if (var->data.mode == ir_var_shader_storage) { |
| var->data.image_read_only = fields[i].image_read_only; |
| var->data.image_write_only = fields[i].image_write_only; |
| var->data.image_coherent = fields[i].image_coherent; |
| var->data.image_volatile = fields[i].image_volatile; |
| var->data.image_restrict = fields[i].image_restrict; |
| } |
| |
| /* Examine var name here since var may get deleted in the next call */ |
| bool var_is_gl_id = is_gl_identifier(var->name); |
| |
| if (redeclaring_per_vertex) { |
| ir_variable *earlier = |
| get_variable_being_redeclared(var, loc, state, |
| true /* allow_all_redeclarations */); |
| if (!var_is_gl_id || earlier == NULL) { |
| _mesa_glsl_error(&loc, state, |
| "redeclaration of gl_PerVertex can only " |
| "include built-in variables"); |
| } else if (earlier->data.how_declared == ir_var_declared_normally) { |
| _mesa_glsl_error(&loc, state, |
| "`%s' has already been redeclared", |
| earlier->name); |
| } else { |
| earlier->data.how_declared = ir_var_declared_in_block; |
| earlier->reinit_interface_type(block_type); |
| } |
| continue; |
| } |
| |
| if (state->symbols->get_variable(var->name) != NULL) |
| _mesa_glsl_error(&loc, state, "`%s' redeclared", var->name); |
| |
| /* Propagate the "binding" keyword into this UBO/SSBO's fields. |
| * The UBO declaration itself doesn't get an ir_variable unless it |
| * has an instance name. This is ugly. |
| */ |
| var->data.explicit_binding = this->layout.flags.q.explicit_binding; |
| var->data.binding = this->layout.binding; |
| |
| if (var->type->is_unsized_array()) { |
| if (var->is_in_shader_storage_block()) { |
| if (!is_unsized_array_last_element(var)) { |
| _mesa_glsl_error(&loc, state, "unsized array `%s' definition: " |
| "only last member of a shader storage block " |
| "can be defined as unsized array", |
| var->name); |
| } |
| var->data.from_ssbo_unsized_array = true; |
| } else { |
| /* From GLSL ES 3.10 spec, section 4.1.9 "Arrays": |
| * |
| * "If an array is declared as the last member of a shader storage |
| * block and the size is not specified at compile-time, it is |
| * sized at run-time. In all other cases, arrays are sized only |
| * at compile-time." |
| */ |
| if (state->es_shader) { |
| _mesa_glsl_error(&loc, state, "unsized array `%s' definition: " |
| "only last member of a shader storage block " |
| "can be defined as unsized array", |
| var->name); |
| } |
| } |
| } |
| |
| state->symbols->add_variable(var); |
| instructions->push_tail(var); |
| } |
| |
| if (redeclaring_per_vertex && block_type != earlier_per_vertex) { |
| /* From section 7.1 ("Built-in Language Variables") of the GLSL 4.10 spec: |
| * |
| * It is also a compilation error ... to redeclare a built-in |
| * block and then use a member from that built-in block that was |
| * not included in the redeclaration. |
| * |
| * This appears to be a clarification to the behaviour established |
| * for gl_PerVertex by GLSL 1.50, therefore we implement this |
| * behaviour regardless of GLSL version. |
| * |
| * To prevent the shader from using a member that was not included in |
| * the redeclaration, we disable any ir_variables that are still |
| * associated with the old declaration of gl_PerVertex (since we've |
| * already updated all of the variables contained in the new |
| * gl_PerVertex to point to it). |
| * |
| * As a side effect this will prevent |
| * validate_intrastage_interface_blocks() from getting confused and |
| * thinking there are conflicting definitions of gl_PerVertex in the |
| * shader. |
| */ |
| foreach_in_list_safe(ir_instruction, node, instructions) { |
| ir_variable *const var = node->as_variable(); |
| if (var != NULL && |
| var->get_interface_type() == earlier_per_vertex && |
| var->data.mode == var_mode) { |
| if (var->data.how_declared == ir_var_declared_normally) { |
| _mesa_glsl_error(&loc, state, |
| "redeclaration of gl_PerVertex cannot " |
| "follow a redeclaration of `%s'", |
| var->name); |
| } |
| state->symbols->disable_variable(var->name); |
| var->remove(); |
| } |
| } |
| } |
| } |
| |
| return NULL; |
| } |
| |
| |
| ir_rvalue * |
| ast_tcs_output_layout::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| YYLTYPE loc = this->get_location(); |
| |
| /* If any tessellation control output layout declaration preceded this |
| * one, make sure it was consistent with this one. |
| */ |
| if (state->tcs_output_vertices_specified && |
| state->out_qualifier->vertices != this->vertices) { |
| _mesa_glsl_error(&loc, state, |
| "tessellation control shader output layout does not " |
| "match previous declaration"); |
| return NULL; |
| } |
| |
| /* If any shader outputs occurred before this declaration and specified an |
| * array size, make sure the size they specified is consistent with the |
| * primitive type. |
| */ |
| unsigned num_vertices = this->vertices; |
| if (state->tcs_output_size != 0 && state->tcs_output_size != num_vertices) { |
| _mesa_glsl_error(&loc, state, |
| "this tessellation control shader output layout " |
| "specifies %u vertices, but a previous output " |
| "is declared with size %u", |
| num_vertices, state->tcs_output_size); |
| return NULL; |
| } |
| |
| state->tcs_output_vertices_specified = true; |
| |
| /* If any shader outputs occurred before this declaration and did not |
| * specify an array size, their size is determined now. |
| */ |
| foreach_in_list (ir_instruction, node, instructions) { |
| ir_variable *var = node->as_variable(); |
| if (var == NULL || var->data.mode != ir_var_shader_out) |
| continue; |
| |
| /* Note: Not all tessellation control shader output are arrays. */ |
| if (!var->type->is_unsized_array() || var->data.patch) |
| continue; |
| |
| if (var->data.max_array_access >= num_vertices) { |
| _mesa_glsl_error(&loc, state, |
| "this tessellation control shader output layout " |
| "specifies %u vertices, but an access to element " |
| "%u of output `%s' already exists", num_vertices, |
| var->data.max_array_access, var->name); |
| } else { |
| var->type = glsl_type::get_array_instance(var->type->fields.array, |
| num_vertices); |
| } |
| } |
| |
| return NULL; |
| } |
| |
| |
| ir_rvalue * |
| ast_gs_input_layout::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| YYLTYPE loc = this->get_location(); |
| |
| /* If any geometry input layout declaration preceded this one, make sure it |
| * was consistent with this one. |
| */ |
| if (state->gs_input_prim_type_specified && |
| state->in_qualifier->prim_type != this->prim_type) { |
| _mesa_glsl_error(&loc, state, |
| "geometry shader input layout does not match" |
| " previous declaration"); |
| return NULL; |
| } |
| |
| /* If any shader inputs occurred before this declaration and specified an |
| * array size, make sure the size they specified is consistent with the |
| * primitive type. |
| */ |
| unsigned num_vertices = vertices_per_prim(this->prim_type); |
| if (state->gs_input_size != 0 && state->gs_input_size != num_vertices) { |
| _mesa_glsl_error(&loc, state, |
| "this geometry shader input layout implies %u vertices" |
| " per primitive, but a previous input is declared" |
| " with size %u", num_vertices, state->gs_input_size); |
| return NULL; |
| } |
| |
| state->gs_input_prim_type_specified = true; |
| |
| /* If any shader inputs occurred before this declaration and did not |
| * specify an array size, their size is determined now. |
| */ |
| foreach_in_list(ir_instruction, node, instructions) { |
| ir_variable *var = node->as_variable(); |
| if (var == NULL || var->data.mode != ir_var_shader_in) |
| continue; |
| |
| /* Note: gl_PrimitiveIDIn has mode ir_var_shader_in, but it's not an |
| * array; skip it. |
| */ |
| |
| if (var->type->is_unsized_array()) { |
| if (var->data.max_array_access >= num_vertices) { |
| _mesa_glsl_error(&loc, state, |
| "this geometry shader input layout implies %u" |
| " vertices, but an access to element %u of input" |
| " `%s' already exists", num_vertices, |
| var->data.max_array_access, var->name); |
| } else { |
| var->type = glsl_type::get_array_instance(var->type->fields.array, |
| num_vertices); |
| } |
| } |
| } |
| |
| return NULL; |
| } |
| |
| |
| ir_rvalue * |
| ast_cs_input_layout::hir(exec_list *instructions, |
| struct _mesa_glsl_parse_state *state) |
| { |
| YYLTYPE loc = this->get_location(); |
| |
| /* If any compute input layout declaration preceded this one, make sure it |
| * was consistent with this one. |
| */ |
| if (state->cs_input_local_size_specified) { |
| for (int i = 0; i < 3; i++) { |
| if (state->cs_input_local_size[i] != this->local_size[i]) { |
| _mesa_glsl_error(&loc, state, |
| "compute shader input layout does not match" |
| " previous declaration"); |
| return NULL; |
| } |
| } |
| } |
| |
| /* From the ARB_compute_shader specification: |
| * |
| * If the local size of the shader in any dimension is greater |
| * than the maximum size supported by the implementation for that |
| * dimension, a compile-time error results. |
| * |
| * It is not clear from the spec how the error should be reported if |
| * the total size of the work group exceeds |
| * MAX_COMPUTE_WORK_GROUP_INVOCATIONS, but it seems reasonable to |
| * report it at compile time as well. |
| */ |
| GLuint64 total_invocations = 1; |
| for (int i = 0; i < 3; i++) { |
| if (this->local_size[i] > state->ctx->Const.MaxComputeWorkGroupSize[i]) { |
| _mesa_glsl_error(&loc, state, |
| "local_size_%c exceeds MAX_COMPUTE_WORK_GROUP_SIZE" |
| " (%d)", 'x' + i, |
| state->ctx->Const.MaxComputeWorkGroupSize[i]); |
| break; |
| } |
| total_invocations *= this->local_size[i]; |
| if (total_invocations > |
| state->ctx->Const.MaxComputeWorkGroupInvocations) { |
| _mesa_glsl_error(&loc, state, |
| "product of local_sizes exceeds " |
| "MAX_COMPUTE_WORK_GROUP_INVOCATIONS (%d)", |
| state->ctx->Const.MaxComputeWorkGroupInvocations); |
| break; |
| } |
| } |
| |
| state->cs_input_local_size_specified = true; |
| for (int i = 0; i < 3; i++) |
| state->cs_input_local_size[i] = this->local_size[i]; |
| |
| /* We may now declare the built-in constant gl_WorkGroupSize (see |
| * builtin_variable_generator::generate_constants() for why we didn't |
| * declare it earlier). |
| */ |
| ir_variable *var = new(state->symbols) |
| ir_variable(glsl_type::uvec3_type, "gl_WorkGroupSize", ir_var_auto); |
| var->data.how_declared = ir_var_declared_implicitly; |
| var->data.read_only = true; |
| instructions->push_tail(var); |
| state->symbols->add_variable(var); |
| ir_constant_data data; |
| memset(&data, 0, sizeof(data)); |
| for (int i = 0; i < 3; i++) |
| data.u[i] = this->local_size[i]; |
| var->constant_value = new(var) ir_constant(glsl_type::uvec3_type, &data); |
| var->constant_initializer = |
| new(var) ir_constant(glsl_type::uvec3_type, &data); |
| var->data.has_initializer = true; |
| |
| return NULL; |
| } |
| |
| |
| static void |
| detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, |
| exec_list *instructions) |
| { |
| bool gl_FragColor_assigned = false; |
| bool gl_FragData_assigned = false; |
| bool user_defined_fs_output_assigned = false; |
| ir_variable *user_defined_fs_output = NULL; |
| |
| /* It would be nice to have proper location information. */ |
| YYLTYPE loc; |
| memset(&loc, 0, sizeof(loc)); |
| |
| foreach_in_list(ir_instruction, node, instructions) { |
| ir_variable *var = node->as_variable(); |
| |
| if (!var || !var->data.assigned) |
| continue; |
| |
| if (strcmp(var->name, "gl_FragColor") == 0) |
| gl_FragColor_assigned = true; |
| else if (strcmp(var->name, "gl_FragData") == 0) |
| gl_FragData_assigned = true; |
| else if (!is_gl_identifier(var->name)) { |
| if (state->stage == MESA_SHADER_FRAGMENT && |
| var->data.mode == ir_var_shader_out) { |
| user_defined_fs_output_assigned = true; |
| user_defined_fs_output = var; |
| } |
| } |
| } |
| |
| /* From the GLSL 1.30 spec: |
| * |
| * "If a shader statically assigns a value to gl_FragColor, it |
| * may not assign a value to any element of gl_FragData. If a |
| * shader statically writes a value to any element of |
| * gl_FragData, it may not assign a value to |
| * gl_FragColor. That is, a shader may assign values to either |
| * gl_FragColor or gl_FragData, but not both. Multiple shaders |
| * linked together must also consistently write just one of |
| * these variables. Similarly, if user declared output |
| * variables are in use (statically assigned to), then the |
| * built-in variables gl_FragColor and gl_FragData may not be |
| * assigned to. These incorrect usages all generate compile |
| * time errors." |
| */ |
| if (gl_FragColor_assigned && gl_FragData_assigned) { |
| _mesa_glsl_error(&loc, state, "fragment shader writes to both " |
| "`gl_FragColor' and `gl_FragData'"); |
| } else if (gl_FragColor_assigned && user_defined_fs_output_assigned) { |
| _mesa_glsl_error(&loc, state, "fragment shader writes to both " |
| "`gl_FragColor' and `%s'", |
| user_defined_fs_output->name); |
| } else if (gl_FragData_assigned && user_defined_fs_output_assigned) { |
| _mesa_glsl_error(&loc, state, "fragment shader writes to both " |
| "`gl_FragData' and `%s'", |
| user_defined_fs_output->name); |
| } |
| } |
| |
| |
| static void |
| remove_per_vertex_blocks(exec_list *instructions, |
| _mesa_glsl_parse_state *state, ir_variable_mode mode) |
| { |
| /* Find the gl_PerVertex interface block of the appropriate (in/out) mode, |
| * if it exists in this shader type. |
| */ |
| const glsl_type *per_vertex = NULL; |
| switch (mode) { |
| case ir_var_shader_in: |
| if (ir_variable *gl_in = state->symbols->get_variable("gl_in")) |
| per_vertex = gl_in->get_interface_type(); |
| break; |
| case ir_var_shader_out: |
| if (ir_variable *gl_Position = |
| state->symbols->get_variable("gl_Position")) { |
| per_vertex = gl_Position->get_interface_type(); |
| } |
| break; |
| default: |
| assert(!"Unexpected mode"); |
| break; |
| } |
| |
| /* If we didn't find a built-in gl_PerVertex interface block, then we don't |
| * need to do anything. |
| */ |
| if (per_vertex == NULL) |
| return; |
| |
| /* If the interface block is used by the shader, then we don't need to do |
| * anything. |
| */ |
| interface_block_usage_visitor v(mode, per_vertex); |
| v.run(instructions); |
| if (v.usage_found()) |
| return; |
| |
| /* Remove any ir_variable declarations that refer to the interface block |
| * we're removing. |
| */ |
| foreach_in_list_safe(ir_instruction, node, instructions) { |
| ir_variable *const var = node->as_variable(); |
| if (var != NULL && var->get_interface_type() == per_vertex && |
| var->data.mode == mode) { |
| state->symbols->disable_variable(var->name); |
| var->remove(); |
| } |
| } |
| } |