diff options
author | Emil Velikov <[email protected]> | 2016-01-18 12:16:48 +0200 |
---|---|---|
committer | Emil Velikov <[email protected]> | 2016-01-26 16:08:33 +0000 |
commit | eb63640c1d38a200a7b1540405051d3ff79d0d8a (patch) | |
tree | da46321a41f309b1d02aeb14d5d5487791c45aeb /src/compiler/glsl/ast_to_hir.cpp | |
parent | a39a8fbbaa129f4e52f2a3ad2747182e9a74d910 (diff) |
glsl: move to compiler/
Signed-off-by: Emil Velikov <[email protected]>
Acked-by: Matt Turner <[email protected]>
Acked-by: Jose Fonseca <[email protected]>
Diffstat (limited to 'src/compiler/glsl/ast_to_hir.cpp')
-rw-r--r-- | src/compiler/glsl/ast_to_hir.cpp | 7583 |
1 files changed, 7583 insertions, 0 deletions
diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp new file mode 100644 index 00000000000..dfd31966eb0 --- /dev/null +++ b/src/compiler/glsl/ast_to_hir.cpp @@ -0,0 +1,7583 @@ +/* + * 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 "compiler/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; + } + + virtual ir_visitor_status visit_enter(ir_expression *ir) + { + /* .length() doesn't actually read anything */ + if (ir->operation == ir_unop_ssbo_unsized_array_length) + return visit_continue_with_parent; + + return visit_continue; + } + +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 value_a LHS of bit-logic op + * \param value_b RHS of bit-logic op + */ +static const struct glsl_type * +bit_logic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b, + ast_operators op, + struct _mesa_glsl_parse_state *state, YYLTYPE *loc) +{ + const glsl_type *type_a = value_a->type; + const glsl_type *type_b = value_b->type; + + 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; + } + + /* Prior to GLSL 4.0 / GL_ARB_gpu_shader5, implicit conversions didn't + * make sense for bitwise operations, as they don't operate on floats. + * + * GLSL 4.0 added implicit int -> uint conversions, which are relevant + * here. It wasn't clear whether or not we should apply them to bitwise + * operations. However, Khronos has decided that they should in future + * language revisions. Applications also rely on this behavior. We opt + * to apply them in general, but issue a portability warning. + * + * See https://www.khronos.org/bugzilla/show_bug.cgi?id=1405 + */ + if (type_a->base_type != type_b->base_type) { + 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 " + "`%s` operator", + ast_expression::operator_string(op)); + return glsl_type::error_type; + } else { + _mesa_glsl_warning(loc, state, + "some implementations may not support implicit " + "int -> uint conversions for `%s' operators; " + "consider casting explicitly for portability", + ast_expression::operator_string(op)); + } + type_a = value_a->type; + type_b = value_b->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(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; + + if (!state->check_version(130, 300, loc, "operator '%%' is reserved")) { + return glsl_type::error_type; + } + + /* Section 5.9 (Expressions) of the GLSL 4.00 specification says: + * + * "The operator modulus (%) operates on signed or unsigned integers or + * integer vectors." + */ + 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 the fundamental types in the operands do not match, then the + * conversions from section 4.1.10 "Implicit Conversions" are applied + * to create matching types." + * + * Note that GLSL 4.00 (and GL_ARB_gpu_shader5) introduced implicit + * int -> uint conversion rules. Prior to that, there were no implicit + * conversions. So it's harmless to apply them universally - no implicit + * conversions will exist. If the types don't match, we'll receive false, + * and raise an error, satisfying the GLSL 1.50 spec, page 56: + * + * "The operand types must both be signed or unsigned." + */ + 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 " + "modulus (%%) operator"); + return glsl_type::error_type; + } + type_a = value_a->type; + type_b = value_b->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. + */ + const glsl_type *lhs_t = lhs->type; + const glsl_type *rhs_t = rhs->type; + bool unsized_array = false; + while(lhs_t->is_array()) { + if (rhs_t == lhs_t) + break; /* the rest of the inner arrays match so break out early */ + if (!rhs_t->is_array()) { + unsized_array = false; + break; /* number of dimensions mismatch */ + } + if (lhs_t->length == rhs_t->length) { + lhs_t = lhs_t->fields.array; + rhs_t = rhs_t->fields.array; + continue; + } else if (lhs_t->is_unsized_array()) { + unsized_array = true; + } else { + unsized_array = false; + break; /* sized array mismatch */ + } + lhs_t = lhs_t->fields.array; + rhs_t = rhs_t->fields.array; + } + if (unsized_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_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); + + *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; +} + +bool +ast_node::has_sequence_subexpression() const +{ + return false; +} + +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], op[1], 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], op[1], 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], op[1], 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], op[1], 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_unsized_array_dim: + assert(!"ast_unsized_array_dim: Should never get here."); + 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; +} + +bool +ast_expression::has_sequence_subexpression() const +{ + switch (this->oper) { + case ast_plus: + case ast_neg: + case ast_bit_not: + case ast_logic_not: + case ast_pre_inc: + case ast_pre_dec: + case ast_post_inc: + case ast_post_dec: + return this->subexpressions[0]->has_sequence_subexpression(); + + case ast_assign: + case ast_add: + case ast_sub: + case ast_mul: + case ast_div: + case ast_mod: + case ast_lshift: + case ast_rshift: + case ast_less: + case ast_greater: + case ast_lequal: + case ast_gequal: + case ast_nequal: + case ast_equal: + case ast_bit_and: + case ast_bit_xor: + case ast_bit_or: + case ast_logic_and: + case ast_logic_or: + case ast_logic_xor: + case ast_array_index: + case ast_mul_assign: + case ast_div_assign: + case ast_add_assign: + case ast_sub_assign: + case ast_mod_assign: + case ast_ls_assign: + case ast_rs_assign: + case ast_and_assign: + case ast_xor_assign: + case ast_or_assign: + return this->subexpressions[0]->has_sequence_subexpression() || + this->subexpressions[1]->has_sequence_subexpression(); + + case ast_conditional: + return this->subexpressions[0]->has_sequence_subexpression() || + this->subexpressions[1]->has_sequence_subexpression() || + this->subexpressions[2]->has_sequence_subexpression(); + + case ast_sequence: + return true; + + case ast_field_selection: + case ast_identifier: + case ast_int_constant: + case ast_uint_constant: + case ast_float_constant: + case ast_bool_constant: + case ast_double_constant: + return false; + + case ast_aggregate: + unreachable("ast_aggregate: Should never get here."); + + case ast_function_call: + unreachable("should be handled by ast_function_expression::hir"); + + case ast_unsized_array_dim: + unreachable("ast_unsized_array_dim: Should never get here."); + } + + return false; +} + +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); + + /** + * Dimensions other than the outermost dimension can by unsized if they + * are immediately sized by a constructor or initializer. + */ + if (((ast_expression*)array_size)->oper == ast_unsized_array_dim) + return 0; + + 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 || array_size->has_sequence_subexpression()) { + _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->check_arrays_of_arrays_allowed(loc)) { + 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); + } + } + + return array_type; +} + +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->contains_opaque()) + && !type->without_array()->is_record(); +} + +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; +} + +/** + * From the OpenGL ES 3.0 spec, 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, (...) If type is float, + * the directive applies to non-precision-qualified floating point type + * (scalar, vector, and matrix) declarations. If type is int, the directive + * applies to all non-precision-qualified integer type (scalar, vector, signed, + * and unsigned) declarations." + * + * We use the symbol table to keep the values of the default precisions for + * each 'type' in each scope and we use the 'type' string from the precision + * statement as key in the symbol table. When we want to retrieve the default + * precision associated with a given glsl_type we need to know the type string + * associated with it. This is what this function returns. + */ +static const char * +get_type_name_for_precision_qualifier(const glsl_type *type) +{ + switch (type->base_type) { + case GLSL_TYPE_FLOAT: + return "float"; + case GLSL_TYPE_UINT: + case GLSL_TYPE_INT: + return "int"; + case GLSL_TYPE_ATOMIC_UINT: + return "atomic_uint"; + case GLSL_TYPE_IMAGE: + /* fallthrough */ + case GLSL_TYPE_SAMPLER: { + const unsigned type_idx = + type->sampler_array + 2 * type->sampler_shadow; + const unsigned offset = type->base_type == GLSL_TYPE_SAMPLER ? 0 : 4; + assert(type_idx < 4); + switch (type->sampler_type) { + case GLSL_TYPE_FLOAT: + switch (type->sampler_dimensionality) { + case GLSL_SAMPLER_DIM_1D: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "sampler1D", "sampler1DArray", + "sampler1DShadow", "sampler1DArrayShadow" + }; + return names[type_idx]; + } + case GLSL_SAMPLER_DIM_2D: { + static const char *const names[8] = { + "sampler2D", "sampler2DArray", + "sampler2DShadow", "sampler2DArrayShadow", + "image2D", "image2DArray", NULL, NULL + }; + return names[offset + type_idx]; + } + case GLSL_SAMPLER_DIM_3D: { + static const char *const names[8] = { + "sampler3D", NULL, NULL, NULL, + "image3D", NULL, NULL, NULL + }; + return names[offset + type_idx]; + } + case GLSL_SAMPLER_DIM_CUBE: { + static const char *const names[8] = { + "samplerCube", "samplerCubeArray", + "samplerCubeShadow", "samplerCubeArrayShadow", + "imageCube", NULL, NULL, NULL + }; + return names[offset + type_idx]; + } + case GLSL_SAMPLER_DIM_MS: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "sampler2DMS", "sampler2DMSArray", NULL, NULL + }; + return names[type_idx]; + } + case GLSL_SAMPLER_DIM_RECT: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "samplerRect", NULL, "samplerRectShadow", NULL + }; + return names[type_idx]; + } + case GLSL_SAMPLER_DIM_BUF: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "samplerBuffer", NULL, NULL, NULL + }; + return names[type_idx]; + } + case GLSL_SAMPLER_DIM_EXTERNAL: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "samplerExternalOES", NULL, NULL, NULL + }; + return names[type_idx]; + } + default: + unreachable("Unsupported sampler/image dimensionality"); + } /* sampler/image float dimensionality */ + break; + case GLSL_TYPE_INT: + switch (type->sampler_dimensionality) { + case GLSL_SAMPLER_DIM_1D: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "isampler1D", "isampler1DArray", NULL, NULL + }; + return names[type_idx]; + } + case GLSL_SAMPLER_DIM_2D: { + static const char *const names[8] = { + "isampler2D", "isampler2DArray", NULL, NULL, + "iimage2D", "iimage2DArray", NULL, NULL + }; + return names[offset + type_idx]; + } + case GLSL_SAMPLER_DIM_3D: { + static const char *const names[8] = { + "isampler3D", NULL, NULL, NULL, + "iimage3D", NULL, NULL, NULL + }; + return names[offset + type_idx]; + } + case GLSL_SAMPLER_DIM_CUBE: { + static const char *const names[8] = { + "isamplerCube", "isamplerCubeArray", NULL, NULL, + "iimageCube", NULL, NULL, NULL + }; + return names[offset + type_idx]; + } + case GLSL_SAMPLER_DIM_MS: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "isampler2DMS", "isampler2DMSArray", NULL, NULL + }; + return names[type_idx]; + } + case GLSL_SAMPLER_DIM_RECT: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "isamplerRect", NULL, "isamplerRectShadow", NULL + }; + return names[type_idx]; + } + case GLSL_SAMPLER_DIM_BUF: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "isamplerBuffer", NULL, NULL, NULL + }; + return names[type_idx]; + } + default: + unreachable("Unsupported isampler/iimage dimensionality"); + } /* sampler/image int dimensionality */ + break; + case GLSL_TYPE_UINT: + switch (type->sampler_dimensionality) { + case GLSL_SAMPLER_DIM_1D: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "usampler1D", "usampler1DArray", NULL, NULL + }; + return names[type_idx]; + } + case GLSL_SAMPLER_DIM_2D: { + static const char *const names[8] = { + "usampler2D", "usampler2DArray", NULL, NULL, + "uimage2D", "uimage2DArray", NULL, NULL + }; + return names[offset + type_idx]; + } + case GLSL_SAMPLER_DIM_3D: { + static const char *const names[8] = { + "usampler3D", NULL, NULL, NULL, + "uimage3D", NULL, NULL, NULL + }; + return names[offset + type_idx]; + } + case GLSL_SAMPLER_DIM_CUBE: { + static const char *const names[8] = { + "usamplerCube", "usamplerCubeArray", NULL, NULL, + "uimageCube", NULL, NULL, NULL + }; + return names[offset + type_idx]; + } + case GLSL_SAMPLER_DIM_MS: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "usampler2DMS", "usampler2DMSArray", NULL, NULL + }; + return names[type_idx]; + } + case GLSL_SAMPLER_DIM_RECT: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "usamplerRect", NULL, "usamplerRectShadow", NULL + }; + return names[type_idx]; + } + case GLSL_SAMPLER_DIM_BUF: { + assert(type->base_type == GLSL_TYPE_SAMPLER); + static const char *const names[4] = { + "usamplerBuffer", NULL, NULL, NULL + }; + return names[type_idx]; + } + default: + unreachable("Unsupported usampler/uimage dimensionality"); + } /* sampler/image uint dimensionality */ + break; + default: + unreachable("Unsupported sampler/image type"); + } /* sampler/image type */ + break; + } /* GLSL_TYPE_SAMPLER/GLSL_TYPE_IMAGE */ + break; + default: + unreachable("Unsupported type"); + } /* base type */ +} + +static unsigned +select_gles_precision(unsigned qual_precision, + const glsl_type *type, + struct _mesa_glsl_parse_state *state, YYLTYPE *loc) +{ + /* Precision qualifiers do not have any meaning in Desktop GLSL. + * In GLES we take the precision from the type qualifier if present, + * otherwise, if the type of the variable allows precision qualifiers at + * all, we look for the default precision qualifier for that type in the + * current scope. + */ + assert(state->es_shader); + + unsigned precision = GLSL_PRECISION_NONE; + if (qual_precision) { + precision = qual_precision; + } else if (precision_qualifier_allowed(type)) { + const char *type_name = + get_type_name_for_precision_qualifier(type->without_array()); + assert(type_name != NULL); + + precision = + state->symbols->get_default_precision_qualifier(type_name); + if (precision == ast_precision_none) { + _mesa_glsl_error(loc, state, + "No precision specified in this scope for type `%s'", + type->name); + } + } + return precision; +} + +const glsl_type * +ast_fully_specified_type::glsl_type(const char **name, + struct _mesa_glsl_parse_state *state) const +{ + return this->specifier->glsl_type(name, state); +} + +/** + * 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->without_array()->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"); + } +} + +static bool +process_qualifier_constant(struct _mesa_glsl_parse_state *state, + YYLTYPE *loc, + const char *qual_indentifier, + ast_expression *const_expression, + unsigned *value) +{ + exec_list dummy_instructions; + + if (const_expression == NULL) { + *value = 0; + return true; + } + + ir_rvalue *const ir = const_expression->hir(&dummy_instructions, state); + + ir_constant *const const_int = ir->constant_expression_value(); + if (const_int == NULL || !const_int->type->is_integer()) { + _mesa_glsl_error(loc, state, "%s must be an integral constant " + "expression", qual_indentifier); + return false; + } + + if (const_int->value.i[0] < 0) { + _mesa_glsl_error(loc, state, "%s layout qualifier is invalid (%d < 0)", + qual_indentifier, const_int->value.u[0]); + return false; + } + + /* If the location 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 location isn't const after all, or + * we are emitting unnecessary instructions. + */ + assert(dummy_instructions.is_empty()); + + *value = const_int->value.u[0]; + return true; +} + +static bool +validate_stream_qualifier(YYLTYPE *loc, struct _mesa_glsl_parse_state *state, + unsigned stream) +{ + if (stream >= state->ctx->Const.MaxVertexStreams) { + _mesa_glsl_error(loc, state, + "invalid stream specified %d is larger than " + "MAX_VERTEX_STREAMS - 1 (%d).", + stream, state->ctx->Const.MaxVertexStreams - 1); + return false; + } + + return true; +} + +static void +apply_explicit_binding(struct _mesa_glsl_parse_state *state, + YYLTYPE *loc, + ir_variable *var, + 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; + } + + unsigned qual_binding; + if (!process_qualifier_constant(state, loc, "binding", qual->binding, + &qual_binding)) { + return; + } + + 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 = %u) for %d UBOs exceeds " + "the maximum number of UBO binding points (%d)", + qual_binding, elements, + ctx->Const.MaxUniformBufferBindings); + return; + } + + /* 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 = %u) for %d SSBOs exceeds " + "the maximum number of SSBO binding points (%d)", + qual_binding, elements, + ctx->Const.MaxShaderStorageBufferBindings); + return; + } + } 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 " + "(%u)", qual_binding, elements, limit); + + return; + } + } else if (base_type->contains_atomic()) { + assert(ctx->Const.MaxAtomicBufferBindings <= MAX_COMBINED_ATOMIC_BUFFERS); + if (qual_binding >= ctx->Const.MaxAtomicBufferBindings) { + _mesa_glsl_error(loc, state, "layout(binding = %d) exceeds the " + " maximum number of atomic counter buffer bindings" + "(%u)", qual_binding, + ctx->Const.MaxAtomicBufferBindings); + + return; + } + } else if ((state->is_version(420, 310) || + state->ARB_shading_language_420pack_enable) && + 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; + } + + } else { + _mesa_glsl_error(loc, state, + "the \"binding\" qualifier only applies to uniform " + "blocks, opaque variables, or arrays thereof"); + return; + } + + var->data.explicit_binding = true; + var->data.binding = qual_binding; + + return; +} + + +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 +apply_explicit_location(const struct ast_type_qualifier *qual, + ir_variable *var, + struct _mesa_glsl_parse_state *state, + YYLTYPE *loc) +{ + bool fail = false; + + unsigned qual_location; + if (!process_qualifier_constant(state, loc, "location", qual->location, + &qual_location)) { + return; + } + + /* 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; + + 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; + + 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; + } + + /* Check if index was set for the uniform instead of the function */ + if (qual->flags.q.explicit_index && qual->flags.q.subroutine) { + _mesa_glsl_error(loc, state, "an index qualifier can only be " + "used with subroutine functions"); + return; + } + + unsigned qual_index; + if (qual->flags.q.explicit_index && + process_qualifier_constant(state, loc, "index", qual->index, + &qual_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 > 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 inline void +validate_array_dimensions(const glsl_type *t, + struct _mesa_glsl_parse_state *state, + YYLTYPE *loc) { + if (t->is_array()) { + t = t->fields.array; + while (t->is_array()) { + if (t->is_unsized_array()) { + _mesa_glsl_error(loc, state, + "only the outermost array dimension can " + "be unsized", + t->name); + break; + } + t = t->fields.array; + } + } +} + +static void +apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual, + ir_variable *var, + struct _mesa_glsl_parse_state *state, + YYLTYPE *loc) +{ + 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; + } + + 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 (qual->flags.q.explicit_location) { + apply_explicit_location(qual, var, state, loc); + } else if (qual->flags.q.explicit_index) { + if (!qual->flags.q.subroutine_def) + _mesa_glsl_error(loc, state, + "explicit index requires explicit location"); + } + + if (qual->flags.q.explicit_binding) { + apply_explicit_binding(state, loc, var, var->type, qual); + } + + if (state->stage == MESA_SHADER_GEOMETRY && + qual->flags.q.out && qual->flags.q.stream) { + unsigned qual_stream; + if (process_qualifier_constant(state, loc, "stream", qual->stream, + &qual_stream) && + validate_stream_qualifier(loc, state, qual_stream)) { + var->data.stream = qual_stream; + } + } + + 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.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"); + } + } + + /* 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; + + const bool uses_deprecated_qualifier = qual->flags.q.attribute + || qual->flags.q.varying; + 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); + } + + /* 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."); + } +} + +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; + + /* Precision qualifiers do not hold any meaning in Desktop GLSL */ + if (state->es_shader) { + var->data.precision = + select_gles_precision(qual->precision, var->type, state, loc); + } + + 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; + else if (qual->flags.q.shared_storage) + var->data.mode = ir_var_shader_shared; + + 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); + + /* 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"); + } + + if (qual->flags.q.shared_storage && state->stage != MESA_SHADER_COMPUTE) { + _mesa_glsl_error(loc, state, + "the shared storage qualifiers can only be used with " + "compute shaders"); + } + + apply_image_qualifier_to_variable(qual, var, state, loc); +} + +/** + * 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 + && var->data.mode == ir_var_shader_in) { + /* 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 uniform %s", + var->name); + } + + /* 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, + "cannot initialize buffer variable %s", + var->name); + } + + /* 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 %s", + var->name); + } + + if ((var->data.mode == ir_var_shader_in) && (state->current_function == NULL)) { + _mesa_glsl_error(&initializer_loc, state, + "cannot initialize %s shader input / %s %s", + _mesa_shader_stage_to_string(state->stage), + (state->stage == MESA_SHADER_VERTEX) + ? "attribute" : "varying", + var->name); + } + + if (var->data.mode == ir_var_shader_out && state->current_function == NULL) { + _mesa_glsl_error(&initializer_loc, state, + "cannot initialize %s shader output %s", + _mesa_shader_stage_to_string(state->stage), + var->name); + } + + /* 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. + * + * Section 4.3 (Storage Qualifiers) of the GLSL ES 1.00.17 spec says: + * + * "Declarations of globals without a storage qualifier, or with + * just the const qualifier, may include initializers, in which case + * they will be initialized before the first line of main() is + * executed. Such initializers must be a constant expression." + * + * The same section of the GLSL ES 3.00.4 spec has similar language. + */ + if (type->qualifier.flags.q.constant + || type->qualifier.flags.q.uniform + || (state->es_shader && state->current_function == NULL)) { + ir_rvalue *new_rhs = validate_assignment(state, initializer_loc, + lhs, rhs, true); + if (new_rhs != NULL) { + rhs = new_rhs; + + /* Section 4.3.3 (Constant Expressions) of the GLSL ES 3.00.4 spec + * says: + * + * "A constant expression is one of + * + * ... + * + * - an expression formed by an operator on operands that are + * all constant expressions, including getting an element of + * a constant array, or a field of a constant structure, or + * components of a constant vector. However, the sequence + * operator ( , ) and the assignment operators ( =, +=, ...) + * are not included in the operators that can create a + * constant expression." + * + * Section 12.43 (Sequence operator and constant expressions) says: + * + * "Should the following construct be allowed? + * + * float a[2,3]; + * + * The expression within the brackets uses the sequence operator + * (',') and returns the integer 3 so the construct is declaring + * a single-dimensional array of size 3. In some languages, the + * construct declares a two-dimensional array. It would be + * preferable to make this construct illegal to avoid confusion. + * + * One possibility is to change the definition of the sequence + * operator so that it does not return a constant-expression and + * hence cannot be used to declare an array size. + * + * RESOLUTION: The result of a sequence operator is not a + * constant-expression." + * + * Section 4.3.3 (Constant Expressions) of the GLSL 4.30.9 spec + * contains language almost identical to the section 4.3.3 in the + * GLSL ES 3.00.4 spec. This is a new limitation for these GLSL + * versions. + */ + ir_constant *constant_value = rhs->constant_expression_value(); + if (!constant_value || + (state->is_version(430, 300) && + decl->initializer->has_sequence_subexpression())) { + const char *const variable_mode = + (type->qualifier.flags.q.constant) + ? "const" + : ((type->qualifier.flags.q.uniform) ? "uniform" : "global"); + + /* 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->has_420pack() + || state->current_function == NULL) { + _mesa_glsl_error(& initializer_loc, state, + "initializer of %s variable `%s' must be a " + "constant expression", + variable_mode, + decl->identifier); + if (var->type->is_numeric()) { + /* Reduce cascading errors. */ + var->constant_value = type->qualifier.flags.q.constant + ? ir_constant::zero(state, var->type) : NULL; + } + } + } else { + rhs = constant_value; + var->constant_value = type->qualifier.flags.q.constant + ? constant_value : NULL; + } + } else { + if (var->type->is_numeric()) { + /* Reduce cascading errors. */ + var->constant_value = type->qualifier.flags.q.constant + ? ir_constant::zero(state, var->type) : NULL; + } + } + } + + 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) { + if (!state->out_qualifier->vertices-> + process_qualifier_constant(state, "vertices", + &num_vertices, false)) { + return; + } + + if (num_vertices > state->Const.MaxPatchVertices) { + _mesa_glsl_error(&loc, state, "vertices (%d) exceeds " + "GL_MAX_PATCH_VERTICES", num_vertices); + return; + } + } + + 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); + } +} + +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) { + unsigned qual_binding; + unsigned qual_offset; + if (process_qualifier_constant(state, &loc, "binding", + type->qualifier.binding, + &qual_binding) + && process_qualifier_constant(state, &loc, "offset", + type->qualifier.offset, + &qual_offset)) { + state->atomic_counter_offsets[qual_binding] = qual_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); + apply_layout_qualifier_to_variable(&this->type->qualifier, var, state, + &loc); + + 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); + } else { + validate_array_dimensions(var_type, state, &loc); + } + + /* 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(state)) { + 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; + + if (this->return_type->qualifier.flags.q.explicit_index) { + unsigned qual_index; + if (process_qualifier_constant(state, &loc, "index", + this->return_type->qualifier.index, + &qual_index)) { + if (!state->has_explicit_uniform_location()) { + _mesa_glsl_error(&loc, state, "subroutine index requires " + "GL_ARB_explicit_uniform_location or " + "GLSL 4.30"); + } else if (qual_index >= MAX_SUBROUTINES) { + _mesa_glsl_error(&loc, state, + "invalid subroutine index (%d) index must " + "be a number between 0 and " + "GL_MAX_SUBROUTINES - 1 (%d)", qual_index, + MAX_SUBROUTINES - 1); + } else { + f->subroutine_index = qual_index; + } + } + } + + 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->has_420pack()) { + 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 (state->es_shader) { + /* Section 4.5.3 (Default Precision Qualifiers) of the GLSL ES 1.00 + * 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 precision + * qualifiers 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. + */ + state->symbols->add_default_precision_qualifier(this->type_name, + this->default_precision); + } + + /* 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. + */ +static unsigned +ast_process_struct_or_iface_block_members(exec_list *instructions, + struct _mesa_glsl_parse_state *state, + exec_list *declarations, + 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 block_stream, + unsigned expl_location) +{ + unsigned decl_count = 0; + + /* 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); + + bool first_member = true; + bool first_member_has_explicit_location; + + unsigned i = 0; + foreach_list_typed (ast_declarator_list, decl_list, link, declarations) { + const char *type_name; + YYLTYPE loc = decl_list->get_location(); + + 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); + + const struct ast_type_qualifier *const qual = + &decl_list->type->qualifier; + + /* 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. + */ + assert(decl_type); + + if (is_interface && decl_type->contains_opaque()) { + _mesa_glsl_error(&loc, state, + "uniform/buffer in non-default interface block contains " + "opaque variable"); + } + + if (decl_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." + */ + _mesa_glsl_error(&loc, state, "atomic counter in structure, " + "shader storage block or uniform block"); + } + + if (decl_type->contains_image()) { + /* FINISHME: Same problem as with atomic counters. + * FINISHME: Request clarification from Khronos and add + * FINISHME: spec quotation here. + */ + _mesa_glsl_error(&loc, state, + "image in structure, shader storage block or " + "uniform block"); + } + + if (qual->flags.q.explicit_binding) { + _mesa_glsl_error(&loc, state, + "binding layout qualifier cannot be applied " + "to struct or interface block members"); + } + + if (is_interface) { + if (!first_member) { + if (!layout->flags.q.explicit_location && + ((first_member_has_explicit_location && + !qual->flags.q.explicit_location) || + (!first_member_has_explicit_location && + qual->flags.q.explicit_location))) { + _mesa_glsl_error(&loc, state, + "when block-level location layout qualifier " + "is not supplied either all members must " + "have a location layout qualifier or all " + "members must not have a location layout " + "qualifier"); + } + } else { + first_member = false; + first_member_has_explicit_location = + qual->flags.q.explicit_location; + } + } + + 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) { + _mesa_glsl_error(&loc, state, + "const storage qualifier cannot be applied " + "to struct or interface block members"); + } + + /* From Section 4.4.2.3 (Geometry Outputs) of the GLSL 4.50 spec: + * + * "A block member may be declared with a stream identifier, but + * the specified stream must match the stream associated with the + * containing block." + */ + if (qual->flags.q.explicit_stream) { + unsigned qual_stream; + if (process_qualifier_constant(state, &loc, "stream", + qual->stream, &qual_stream) && + qual_stream != block_stream) { + _mesa_glsl_error(&loc, state, "stream layout qualifier on " + "interface block member does not match " + "the interface block (%u vs %u)", qual_stream, + block_stream); + } + } + + 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."); + } + + 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, decl_type, NULL); + } + + if (qual->flags.q.read_only && qual->flags.q.write_only) { + _mesa_glsl_error(&loc, state, "buffer variable can't be both " + "readonly and writeonly."); + } + + foreach_list_typed (ast_declaration, decl, link, + &decl_list->declarations) { + YYLTYPE loc = decl->get_location(); + + if (!allow_reserved_names) + validate_identifier(decl->identifier, loc, state); + + const struct glsl_type *field_type = + process_array_type(&loc, decl_type, decl->array_specifier, state); + validate_array_dimensions(field_type, state, &loc); + fields[i].type = field_type; + fields[i].name = decl->identifier; + 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; + fields[i].precision = qual->precision; + + if (qual->flags.q.explicit_location) { + unsigned qual_location; + if (process_qualifier_constant(state, &loc, "location", + qual->location, &qual_location)) { + fields[i].location = VARYING_SLOT_VAR0 + qual_location; + expl_location = fields[i].location + + fields[i].type->count_attribute_slots(false); + } + } else { + if (layout && layout->flags.q.explicit_location) { + fields[i].location = expl_location; + expl_location += fields[i].type->count_attribute_slots(false); + } else { + fields[i].location = -1; + } + } + + /* 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) { + /* For readonly and writeonly qualifiers the field definition, + * if set, overwrites the layout qualifier. + */ + if (qual->flags.q.read_only) { + fields[i].image_read_only = true; + fields[i].image_write_only = false; + } else if (qual->flags.q.write_only) { + fields[i].image_read_only = false; + fields[i].image_write_only = true; + } else { + fields[i].image_read_only = layout->flags.q.read_only; + fields[i].image_write_only = layout->flags.q.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++; + + unsigned expl_location = 0; + if (layout && layout->flags.q.explicit_location) { + if (!process_qualifier_constant(state, &loc, "location", + layout->location, &expl_location)) { + return NULL; + } else { + expl_location = VARYING_SLOT_VAR0 + expl_location; + } + } + + glsl_struct_field *fields; + unsigned decl_count = + ast_process_struct_or_iface_block_members(instructions, + state, + &this->declarations, + &fields, + false, + GLSL_MATRIX_LAYOUT_INHERITED, + false /* allow_reserved_names */, + ir_var_auto, + layout, + 0, /* for interface only */ + expl_location); + + 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++; + + /* For blocks that accept memory qualifiers (i.e. shader storage), verify + * that we don't have incompatible qualifiers + */ + if (this->layout.flags.q.read_only && this->layout.flags.q.write_only) { + _mesa_glsl_error(&loc, state, + "Interface block sets both readonly and writeonly"); + } + + unsigned qual_stream; + if (!process_qualifier_constant(state, &loc, "stream", this->layout.stream, + &qual_stream) || + !validate_stream_qualifier(&loc, state, qual_stream)) { + /* If the stream qualifier is invalid it doesn't make sense to continue + * on and try to compare stream layouts on member variables against it + * so just return early. + */ + return NULL; + } + + unsigned expl_location = 0; + if (layout.flags.q.explicit_location) { + if (!process_qualifier_constant(state, &loc, "location", + layout.location, &expl_location)) { + return NULL; + } else { + expl_location = VARYING_SLOT_VAR0 + expl_location; + } + } + + unsigned int num_variables = + ast_process_struct_or_iface_block_members(&declared_variables, + state, + &this->declarations, + &fields, + true, + matrix_layout, + redeclaring_per_vertex, + var_mode, + &this->layout, + qual_stream, + expl_location); + + 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 || + !this->array_specifier->is_single_dimension()) { + _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; + fields[i].precision = + earlier_per_vertex->fields.structure[j].precision; + } + } + + /* 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 (!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) { + const glsl_type *block_array_type = + process_array_type(&loc, block_type, this->array_specifier, state); + + /* 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 (block_array_type->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)); + } + } + + /* 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"); + } + + 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 { + if (this->layout.flags.q.explicit_binding) { + apply_explicit_binding(state, &loc, var, var->type, + &this->layout); + } + + var->data.stream = qual_stream; + if (layout.flags.q.explicit_location) { + var->data.location = expl_location; + var->data.explicit_location = true; + } + + 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->data.stream = qual_stream; + var->data.location = fields[i].location; + if (fields[i].location != -1) + var->data.explicit_location = true; + var->init_interface_type(block_type); + + if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform) + var->data.read_only = true; + + /* Precision qualifiers do not have any meaning in Desktop GLSL */ + if (state->es_shader) { + var->data.precision = + select_gles_precision(fields[i].precision, fields[i].type, + state, &loc); + } + + 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 (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. + */ + if (this->layout.flags.q.explicit_binding) { + apply_explicit_binding(state, &loc, var, + var->get_interface_type(), &this->layout); + } + + 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(); + + unsigned num_vertices; + if (!state->out_qualifier->vertices-> + process_qualifier_constant(state, "vertices", &num_vertices, + false)) { + /* return here to stop cascading incorrect error messages */ + 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. + */ + 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(); + + /* 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; + unsigned qual_local_size[3]; + for (int i = 0; i < 3; i++) { + + char *local_size_str = ralloc_asprintf(NULL, "invalid local_size_%c", + 'x' + i); + /* Infer a local_size of 1 for unspecified dimensions */ + if (this->local_size[i] == NULL) { + qual_local_size[i] = 1; + } else if (!this->local_size[i]-> + process_qualifier_constant(state, local_size_str, + &qual_local_size[i], false)) { + ralloc_free(local_size_str); + return NULL; + } + ralloc_free(local_size_str); + + if (qual_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 *= qual_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; + } + } + + /* 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] != qual_local_size[i]) { + _mesa_glsl_error(&loc, state, + "compute shader input layout does not match" + " previous declaration"); + return NULL; + } + } + } + + state->cs_input_local_size_specified = true; + for (int i = 0; i < 3; i++) + state->cs_input_local_size[i] = qual_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] = qual_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 gl_FragSecondaryColor_assigned = false; + bool gl_FragSecondaryData_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 (strcmp(var->name, "gl_SecondaryFragColorEXT") == 0) + gl_FragSecondaryColor_assigned = true; + else if (strcmp(var->name, "gl_SecondaryFragDataEXT") == 0) + gl_FragSecondaryData_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_FragSecondaryColor_assigned && gl_FragSecondaryData_assigned) { + _mesa_glsl_error(&loc, state, "fragment shader writes to both " + "`gl_FragSecondaryColorEXT' and" + " `gl_FragSecondaryDataEXT'"); + } else if (gl_FragColor_assigned && gl_FragSecondaryData_assigned) { + _mesa_glsl_error(&loc, state, "fragment shader writes to both " + "`gl_FragColor' and" + " `gl_FragSecondaryDataEXT'"); + } else if (gl_FragData_assigned && gl_FragSecondaryColor_assigned) { + _mesa_glsl_error(&loc, state, "fragment shader writes to both " + "`gl_FragData' and" + " `gl_FragSecondaryColorEXT'"); + } 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); + } + + if ((gl_FragSecondaryColor_assigned || gl_FragSecondaryData_assigned) && + !state->EXT_blend_func_extended_enable) { + _mesa_glsl_error(&loc, state, + "Dual source blending requires EXT_blend_func_extended"); + } +} + + +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(); + } + } +} |