diff options
author | marha <marha@users.sourceforge.net> | 2013-07-12 08:25:37 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2013-07-12 08:25:37 +0200 |
commit | 66b46719d55e60d53b42858770d6ac40d079ab13 (patch) | |
tree | aad06d011ed8b820685f72ada34e56ee0f2580c6 /mesalib/src/glsl | |
parent | f8f0209a691e0d0838d1ef9d602ebacafee2a233 (diff) | |
parent | ffce4319c2fb6f4f663cc5a9660e1d5837fcde87 (diff) | |
download | vcxsrv-66b46719d55e60d53b42858770d6ac40d079ab13.tar.gz vcxsrv-66b46719d55e60d53b42858770d6ac40d079ab13.tar.bz2 vcxsrv-66b46719d55e60d53b42858770d6ac40d079ab13.zip |
Merge remote-tracking branch 'origin/released'
* origin/released:
libxtrans fontconfig mesa xserver git update 12 Jul 2013
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r-- | mesalib/src/glsl/ast.h | 70 | ||||
-rw-r--r-- | mesalib/src/glsl/ast_function.cpp | 275 | ||||
-rw-r--r-- | mesalib/src/glsl/ast_to_hir.cpp | 20 | ||||
-rw-r--r-- | mesalib/src/glsl/ast_type.cpp | 3 | ||||
-rw-r--r-- | mesalib/src/glsl/builtin_compiler/Makefile.am | 3 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_lexer.ll | 4 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_parser.yy | 60 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_parser_extras.cpp | 204 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_symbol_table.cpp | 29 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_symbol_table.h | 2 | ||||
-rw-r--r-- | mesalib/src/glsl/opt_flip_matrices.cpp | 2 |
11 files changed, 596 insertions, 76 deletions
diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index f73265bf3..ff4bb0d6a 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -193,7 +193,8 @@ enum ast_operators { ast_float_constant, ast_bool_constant, - ast_sequence + ast_sequence, + ast_aggregate }; /** @@ -296,6 +297,29 @@ private: bool cons; }; +/** + * C-style aggregate initialization class + * + * Represents C-style initializers of vectors, matrices, arrays, and + * structures. E.g., vec3 pos = {1.0, 0.0, -1.0} is equivalent to + * vec3 pos = vec3(1.0, 0.0, -1.0). + * + * Specified in GLSL 4.20 and GL_ARB_shading_language_420pack. + * + * \sa _mesa_ast_set_aggregate_type + */ +class ast_aggregate_initializer : public ast_expression { +public: + ast_aggregate_initializer() + : ast_expression(ast_aggregate, NULL, NULL, NULL) + { + /* empty */ + } + + ast_type_specifier *constructor_type; + virtual ir_rvalue *hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state); +}; /** * Number of possible operators for an ast_expression @@ -321,13 +345,13 @@ public: class ast_declaration : public ast_node { public: - ast_declaration(const char *identifier, int is_array, ast_expression *array_size, + ast_declaration(const char *identifier, bool is_array, ast_expression *array_size, ast_expression *initializer); virtual void print(void) const; const char *identifier; - int is_array; + bool is_array; ast_expression *array_size; ast_expression *initializer; @@ -457,6 +481,19 @@ class ast_declarator_list; class ast_struct_specifier : public ast_node { public: + /** + * \brief Make a shallow copy of an ast_struct_specifier. + * + * Use only if the objects are allocated from the same context and will not + * be modified. Zeros the inherited ast_node's fields. + */ + ast_struct_specifier(const ast_struct_specifier& that): + ast_node(), name(that.name), declarations(that.declarations), + is_declaration(that.is_declaration) + { + /* empty */ + } + ast_struct_specifier(const char *identifier, ast_declarator_list *declarator_list); virtual void print(void) const; @@ -467,12 +504,29 @@ public: const char *name; /* List of ast_declarator_list * */ exec_list declarations; + bool is_declaration; }; class ast_type_specifier : public ast_node { public: + /** + * \brief Make a shallow copy of an ast_type_specifier, specifying array + * fields. + * + * Use only if the objects are allocated from the same context and will not + * be modified. Zeros the inherited ast_node's fields. + */ + ast_type_specifier(const ast_type_specifier *that, bool is_array, + ast_expression *array_size) + : ast_node(), type_name(that->type_name), structure(that->structure), + is_array(is_array), array_size(array_size), precision(that->precision), + is_precision_statement(that->is_precision_statement) + { + /* empty */ + } + /** Construct a type specifier from a type name */ ast_type_specifier(const char *name) : type_name(name), structure(NULL), @@ -502,7 +556,7 @@ public: const char *type_name; ast_struct_specifier *structure; - int is_array; + bool is_array; ast_expression *array_size; unsigned precision:2; @@ -530,6 +584,7 @@ public: struct _mesa_glsl_parse_state *state); ast_fully_specified_type *type; + /** List of 'ast_declaration *' */ exec_list declarations; /** @@ -569,7 +624,7 @@ public: ast_fully_specified_type *type; const char *identifier; - int is_array; + bool is_array; ast_expression *array_size; static void parameters_to_hir(exec_list *ast_parameters, @@ -864,6 +919,11 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, ir_rvalue *array, ir_rvalue *idx, YYLTYPE &loc, YYLTYPE &idx_loc); +extern void +_mesa_ast_set_aggregate_type(const ast_type_specifier *type, + ast_expression *expr, + _mesa_glsl_parse_state *state); + void emit_function(_mesa_glsl_parse_state *state, ir_function *f); diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp index 00e0c05dd..39182639f 100644 --- a/mesalib/src/glsl/ast_function.cpp +++ b/mesalib/src/glsl/ast_function.cpp @@ -610,6 +610,120 @@ dereference_component(ir_rvalue *src, unsigned component) static ir_rvalue * +process_vec_mat_constructor(exec_list *instructions, + const glsl_type *constructor_type, + YYLTYPE *loc, exec_list *parameters, + struct _mesa_glsl_parse_state *state) +{ + void *ctx = state; + + /* The ARB_shading_language_420pack spec says: + * + * "If an initializer is a list of initializers enclosed in curly braces, + * the variable being declared must be a vector, a matrix, an array, or a + * structure. + * + * int i = { 1 }; // illegal, i is not an aggregate" + */ + if (constructor_type->vector_elements <= 1) { + _mesa_glsl_error(loc, state, "Aggregates can only initialize vectors, " + "matrices, arrays, and structs"); + return ir_rvalue::error_value(ctx); + } + + exec_list actual_parameters; + const unsigned parameter_count = + process_parameters(instructions, &actual_parameters, parameters, state); + + if (parameter_count == 0 + || (constructor_type->is_vector() && + constructor_type->vector_elements != parameter_count) + || (constructor_type->is_matrix() && + constructor_type->matrix_columns != parameter_count)) { + _mesa_glsl_error(loc, state, "%s constructor must have %u parameters", + constructor_type->is_vector() ? "vector" : "matrix", + constructor_type->vector_elements); + return ir_rvalue::error_value(ctx); + } + + bool all_parameters_are_constant = true; + + /* Type cast each parameter and, if possible, fold constants. */ + foreach_list_safe(n, &actual_parameters) { + ir_rvalue *ir = (ir_rvalue *) n; + ir_rvalue *result = ir; + + /* Apply implicit conversions (not the scalar constructor rules!). See + * the spec quote above. */ + if (constructor_type->is_float()) { + const glsl_type *desired_type = + glsl_type::get_instance(GLSL_TYPE_FLOAT, + ir->type->vector_elements, + ir->type->matrix_columns); + if (result->type->can_implicitly_convert_to(desired_type)) { + /* Even though convert_component() implements the constructor + * conversion rules (not the implicit conversion rules), its safe + * to use it here because we already checked that the implicit + * conversion is legal. + */ + result = convert_component(ir, desired_type); + } + } + + if (constructor_type->is_matrix()) { + if (result->type != constructor_type->column_type()) { + _mesa_glsl_error(loc, state, "type error in matrix constructor: " + "expected: %s, found %s", + constructor_type->column_type()->name, + result->type->name); + return ir_rvalue::error_value(ctx); + } + } else if (result->type != constructor_type->get_scalar_type()) { + _mesa_glsl_error(loc, state, "type error in vector constructor: " + "expected: %s, found %s", + constructor_type->get_scalar_type()->name, + result->type->name); + return ir_rvalue::error_value(ctx); + } + + /* Attempt to convert the parameter to a constant valued expression. + * After doing so, track whether or not all the parameters to the + * constructor are trivially constant valued expressions. + */ + ir_rvalue *const constant = result->constant_expression_value(); + + if (constant != NULL) + result = constant; + else + all_parameters_are_constant = false; + + ir->replace_with(result); + } + + if (all_parameters_are_constant) + return new(ctx) ir_constant(constructor_type, &actual_parameters); + + ir_variable *var = new(ctx) ir_variable(constructor_type, "vec_mat_ctor", + ir_var_temporary); + instructions->push_tail(var); + + int i = 0; + foreach_list(node, &actual_parameters) { + ir_rvalue *rhs = (ir_rvalue *) node; + ir_rvalue *lhs = new(ctx) ir_dereference_array(var, + new(ctx) ir_constant(i)); + + ir_instruction *assignment = new(ctx) ir_assignment(lhs, rhs, NULL); + instructions->push_tail(assignment); + + i++; + } + + return new(ctx) ir_dereference_variable(var); +} + + +static ir_rvalue * process_array_constructor(exec_list *instructions, const glsl_type *constructor_type, YYLTYPE *loc, exec_list *parameters, @@ -648,7 +762,7 @@ process_array_constructor(exec_list *instructions, _mesa_glsl_error(loc, state, "array constructor must have %s %u " "parameter%s", - (constructor_type->length != 0) ? "at least" : "exactly", + (constructor_type->length == 0) ? "at least" : "exactly", min_param, (min_param <= 1) ? "" : "s"); return ir_rvalue::error_value(ctx); } @@ -690,6 +804,7 @@ process_array_constructor(exec_list *instructions, "expected: %s, found %s", constructor_type->element_type()->name, result->type->name); + return ir_rvalue::error_value(ctx); } /* Attempt to convert the parameter to a constant valued expression. @@ -1259,6 +1374,63 @@ emit_inline_record_constructor(const glsl_type *type, } +static ir_rvalue * +process_record_constructor(exec_list *instructions, + const glsl_type *constructor_type, + YYLTYPE *loc, exec_list *parameters, + struct _mesa_glsl_parse_state *state) +{ + void *ctx = state; + exec_list actual_parameters; + + process_parameters(instructions, &actual_parameters, + parameters, state); + + exec_node *node = actual_parameters.head; + for (unsigned i = 0; i < constructor_type->length; i++) { + ir_rvalue *ir = (ir_rvalue *) node; + + if (node->is_tail_sentinel()) { + _mesa_glsl_error(loc, state, + "insufficient parameters to constructor for `%s'", + constructor_type->name); + return ir_rvalue::error_value(ctx); + } + + if (apply_implicit_conversion(constructor_type->fields.structure[i].type, + ir, state)) { + node->replace_with(ir); + } else { + _mesa_glsl_error(loc, state, + "parameter type mismatch in constructor for `%s.%s' " + "(%s vs %s)", + constructor_type->name, + constructor_type->fields.structure[i].name, + ir->type->name, + constructor_type->fields.structure[i].type->name); + return ir_rvalue::error_value(ctx);; + } + + node = node->next; + } + + if (!node->is_tail_sentinel()) { + _mesa_glsl_error(loc, state, "too many parameters in constructor " + "for `%s'", constructor_type->name); + return ir_rvalue::error_value(ctx); + } + + ir_rvalue *const constant = + constant_record_constructor(constructor_type, &actual_parameters, + state); + + return (constant != NULL) + ? constant + : emit_inline_record_constructor(constructor_type, instructions, + &actual_parameters, state); +} + + ir_rvalue * ast_function_expression::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) @@ -1310,63 +1482,24 @@ ast_function_expression::hir(exec_list *instructions, } - /* There are two kinds of constructor call. Constructors for built-in - * language types, such as mat4 and vec2, are free form. The only - * requirement is that the parameters must provide enough values of the - * correct scalar type. Constructors for arrays and structures must - * have the exact number of parameters with matching types in the - * correct order. These constructors follow essentially the same type - * matching rules as functions. + /* There are two kinds of constructor calls. Constructors for arrays and + * structures must have the exact number of arguments with matching types + * in the correct order. These constructors follow essentially the same + * type matching rules as functions. + * + * Constructors for built-in language types, such as mat4 and vec2, are + * free form. The only requirements are that the parameters must provide + * enough values of the correct scalar type and that no arguments are + * given past the last used argument. + * + * When using the C-style initializer syntax from GLSL 4.20, constructors + * must have the exact number of arguments with matching types in the + * correct order. */ if (constructor_type->is_record()) { - exec_list actual_parameters; - - process_parameters(instructions, &actual_parameters, - &this->expressions, state); - - exec_node *node = actual_parameters.head; - for (unsigned i = 0; i < constructor_type->length; i++) { - ir_rvalue *ir = (ir_rvalue *) node; - - if (node->is_tail_sentinel()) { - _mesa_glsl_error(&loc, state, - "insufficient parameters to constructor " - "for `%s'", - constructor_type->name); - return ir_rvalue::error_value(ctx); - } - - if (apply_implicit_conversion(constructor_type->fields.structure[i].type, - ir, state)) { - node->replace_with(ir); - } else { - _mesa_glsl_error(&loc, state, - "parameter type mismatch in constructor " - "for `%s.%s' (%s vs %s)", - constructor_type->name, - constructor_type->fields.structure[i].name, - ir->type->name, - constructor_type->fields.structure[i].type->name); - return ir_rvalue::error_value(ctx);; - } - - node = node->next; - } - - if (!node->is_tail_sentinel()) { - _mesa_glsl_error(&loc, state, "too many parameters in constructor " - "for `%s'", constructor_type->name); - return ir_rvalue::error_value(ctx); - } - - ir_rvalue *const constant = - constant_record_constructor(constructor_type, &actual_parameters, - state); - - return (constant != NULL) - ? constant - : emit_inline_record_constructor(constructor_type, instructions, - &actual_parameters, state); + return process_record_constructor(instructions, constructor_type, + &loc, &this->expressions, + state); } if (!constructor_type->is_numeric() && !constructor_type->is_boolean()) @@ -1566,3 +1699,33 @@ ast_function_expression::hir(exec_list *instructions, return ir_rvalue::error_value(ctx); } + +ir_rvalue * +ast_aggregate_initializer::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + void *ctx = state; + YYLTYPE loc = this->get_location(); + const char *name; + const glsl_type *const constructor_type = + this->constructor_type->glsl_type(&name, state); + + if (!state->ARB_shading_language_420pack_enable) { + _mesa_glsl_error(&loc, state, "C-style initialization requires the " + "GL_ARB_shading_language_420pack extension"); + return ir_rvalue::error_value(ctx); + } + + if (this->constructor_type->is_array) { + return process_array_constructor(instructions, constructor_type, &loc, + &this->expressions, state); + } + + if (this->constructor_type->structure) { + return process_record_constructor(instructions, constructor_type, &loc, + &this->expressions, state); + } + + return process_vec_mat_constructor(instructions, constructor_type, &loc, + &this->expressions, state); +} diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index cbd9ea357..01203134d 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -1068,6 +1068,10 @@ ast_expression::hir(exec_list *instructions, 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); @@ -4001,7 +4005,19 @@ ast_type_specifier::hir(exec_list *instructions, return NULL; } - if (this->structure != 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; @@ -4229,6 +4245,8 @@ ast_interface_block::hir(exec_list *instructions, var_mode = ir_var_uniform; iface_type_name = "uniform"; } else { + var_mode = ir_var_auto; + iface_type_name = "UNKNOWN"; assert(!"interface block layout qualifier not found!"); } diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp index 29493e2f6..be84550da 100644 --- a/mesalib/src/glsl/ast_type.cpp +++ b/mesalib/src/glsl/ast_type.cpp @@ -22,9 +22,6 @@ */ #include "ast.h" -extern "C" { -#include "program/symbol_table.h" -} void ast_type_specifier::print(void) const diff --git a/mesalib/src/glsl/builtin_compiler/Makefile.am b/mesalib/src/glsl/builtin_compiler/Makefile.am index e11a17fbe..823d546e1 100644 --- a/mesalib/src/glsl/builtin_compiler/Makefile.am +++ b/mesalib/src/glsl/builtin_compiler/Makefile.am @@ -26,7 +26,8 @@ AM_CFLAGS = \ -I $(top_srcdir)/src/mesa \ -I $(GLSL_SRCDIR) \ -I $(GLSL_SRCDIR)/glcpp \ - -I $(GLSL_BUILDDIR) + -I $(GLSL_BUILDDIR) \ + $(VISIBILITY_CFLAGS) if CROSS_COMPILING proxyCC = @CC_FOR_BUILD@ diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll index 008ef303d..e66ce7bee 100644 --- a/mesalib/src/glsl/glsl_lexer.ll +++ b/mesalib/src/glsl/glsl_lexer.ll @@ -72,7 +72,7 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *); alt_expr, token) \ do { \ if (yyextra->is_version(allowed_glsl, allowed_glsl_es) \ - || alt_expr) { \ + || (alt_expr)) { \ return token; \ } else if (yyextra->is_version(reserved_glsl, \ reserved_glsl_es)) { \ @@ -522,7 +522,7 @@ image2DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE2DARRAYSHADOW); imageBuffer KEYWORD(130, 300, 0, 0, IMAGEBUFFER); iimageBuffer KEYWORD(130, 300, 0, 0, IIMAGEBUFFER); uimageBuffer KEYWORD(130, 300, 0, 0, UIMAGEBUFFER); -row_major KEYWORD_WITH_ALT(130, 0, 140, 0, yyextra->ARB_uniform_buffer_object_enable, ROW_MAJOR); +row_major KEYWORD_WITH_ALT(130, 0, 140, 0, yyextra->ARB_uniform_buffer_object_enable && !yyextra->es_shader, ROW_MAJOR); /* Additional reserved words in GLSL 1.40 */ isampler2DRect KEYWORD(140, 300, 140, 0, ISAMPLER2DRECT); diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index 56367f8c6..78f5bf6f4 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -221,6 +221,7 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg) %type <declarator_list> init_declarator_list %type <declarator_list> single_declaration %type <expression> initializer +%type <expression> initializer_list %type <node> declaration %type <node> declaration_statement %type <node> jump_statement @@ -961,6 +962,11 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); + if ($7->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$7; + ast_type_specifier *type = new(ctx) ast_type_specifier($1->type->specifier, true, NULL); + _mesa_ast_set_aggregate_type(type, ai, state); + } } | init_declarator_list ',' any_identifier '[' constant_expression ']' '=' initializer { @@ -971,6 +977,11 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); + if ($8->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$8; + ast_type_specifier *type = new(ctx) ast_type_specifier($1->type->specifier, true, $5); + _mesa_ast_set_aggregate_type(type, ai, state); + } } | init_declarator_list ',' any_identifier '=' initializer { @@ -981,6 +992,10 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); + if ($5->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$5; + _mesa_ast_set_aggregate_type($1->type->specifier, ai, state); + } } ; @@ -1028,6 +1043,11 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); + if ($6->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$6; + ast_type_specifier *type = new(ctx) ast_type_specifier($1->specifier, true, NULL); + _mesa_ast_set_aggregate_type(type, ai, state); + } } | fully_specified_type any_identifier '[' constant_expression ']' '=' initializer { @@ -1037,6 +1057,11 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); + if ($7->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$7; + ast_type_specifier *type = new(ctx) ast_type_specifier($1->specifier, true, $4); + _mesa_ast_set_aggregate_type(type, ai, state); + } } | fully_specified_type any_identifier '=' initializer { @@ -1046,6 +1071,9 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); + if ($4->oper == ast_aggregate) { + _mesa_ast_set_aggregate_type($1->specifier, $4, state); + } } | INVARIANT variable_identifier // Vertex only. { @@ -1155,6 +1183,12 @@ layout_qualifier_id: $$.flags.q.shared = 1; } else if (strcmp($1, "column_major") == 0) { $$.flags.q.column_major = 1; + /* "row_major" is a reserved word in GLSL 1.30+. Its token is parsed + * below in the interface_block_layout_qualifier rule. + * + * It is not a reserved word in GLSL ES 3.00, so it's handled here as + * an identifier. + */ } else if (strcmp($1, "row_major") == 0) { $$.flags.q.row_major = 1; } @@ -1177,9 +1211,6 @@ layout_qualifier_id: memset(& $$, 0, sizeof($$)); if (state->ARB_explicit_attrib_location_enable) { - /* FINISHME: Handle 'index' once GL_ARB_blend_func_exteneded and - * FINISHME: GLSL 1.30 (or later) are supported. - */ if (strcmp("location", $1) == 0) { $$.flags.q.explicit_location = 1; @@ -1503,6 +1534,7 @@ struct_specifier: $$ = new(ctx) ast_struct_specifier($2, $4); $$->set_location(yylloc); state->symbols->add_type($2, glsl_type::void_type); + state->symbols->add_type_ast($2, new(ctx) ast_type_specifier($$)); } | STRUCT '{' struct_declaration_list '}' { @@ -1570,6 +1602,28 @@ struct_declarator: initializer: assignment_expression + | '{' initializer_list '}' + { + $$ = $2; + } + | '{' initializer_list ',' '}' + { + $$ = $2; + } + ; + +initializer_list: + initializer + { + void *ctx = state; + $$ = new(ctx) ast_aggregate_initializer(); + $$->set_location(yylloc); + $$->expressions.push_tail(& $1->link); + } + | initializer_list ',' initializer + { + $1->expressions.push_tail(& $3->link); + } ; declaration_statement: diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index f4087df30..055dfa993 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -663,6 +663,194 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp, return true; } + +/** + * Returns the name of the type of a column of a matrix. E.g., + * + * "mat3" -> "vec3" + * "mat4x2" -> "vec2" + */ +static const char * +_mesa_ast_get_matrix_column_type_name(const char *matrix_type_name) +{ + static const char *vec_name[] = { "vec2", "vec3", "vec4" }; + + /* The number of elements in a row of a matrix is specified by the last + * character of the matrix type name. + */ + long rows = strtol(matrix_type_name + strlen(matrix_type_name) - 1, + NULL, 10); + return vec_name[rows - 2]; +} + +/** + * Recurses through <type> and <expr> if <expr> is an aggregate initializer + * and sets <expr>'s <constructor_type> field to <type>. Gives later functions + * (process_array_constructor, et al) sufficient information to do type + * checking. + * + * Operates on assignments involving an aggregate initializer. E.g., + * + * vec4 pos = {1.0, -1.0, 0.0, 1.0}; + * + * or more ridiculously, + * + * struct S { + * vec4 v[2]; + * }; + * + * struct { + * S a[2], b; + * int c; + * } aggregate = { + * { + * { + * { + * {1.0, 2.0, 3.0, 4.0}, // a[0].v[0] + * {5.0, 6.0, 7.0, 8.0} // a[0].v[1] + * } // a[0].v + * }, // a[0] + * { + * { + * {1.0, 2.0, 3.0, 4.0}, // a[1].v[0] + * {5.0, 6.0, 7.0, 8.0} // a[1].v[1] + * } // a[1].v + * } // a[1] + * }, // a + * { + * { + * {1.0, 2.0, 3.0, 4.0}, // b.v[0] + * {5.0, 6.0, 7.0, 8.0} // b.v[1] + * } // b.v + * }, // b + * 4 // c + * }; + * + * This pass is necessary because the right-hand side of <type> e = { ... } + * doesn't contain sufficient information to determine if the types match. + */ +void +_mesa_ast_set_aggregate_type(const ast_type_specifier *type, + ast_expression *expr, + _mesa_glsl_parse_state *state) +{ + void *ctx = state; + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)expr; + ai->constructor_type = (ast_type_specifier *)type; + + bool is_declaration = ai->constructor_type->structure != NULL; + if (!is_declaration) { + /* Look up <type> name in the symbol table to see if it's a struct. */ + const ast_type_specifier *struct_type = + state->symbols->get_type_ast(type->type_name); + ai->constructor_type->structure = + struct_type ? new(ctx) ast_struct_specifier(*struct_type->structure) + : NULL; + } + + /* If the aggregate is an array, recursively set its elements' types. */ + if (type->is_array) { + /* We want to set the element type which is not an array itself, so make + * a copy of the array type and set its is_array field to false. + * + * E.g., if <type> if struct S[2] we want to set each element's type to + * struct S. + * + * FINISHME: Update when ARB_array_of_arrays is supported. + */ + const ast_type_specifier *non_array_type = + new(ctx) ast_type_specifier(type, false, NULL); + + for (exec_node *expr_node = ai->expressions.head; + !expr_node->is_tail_sentinel(); + expr_node = expr_node->next) { + ast_expression *expr = exec_node_data(ast_expression, expr_node, + link); + + if (expr->oper == ast_aggregate) + _mesa_ast_set_aggregate_type(non_array_type, expr, state); + } + + /* If the aggregate is a struct, recursively set its fields' types. */ + } else if (ai->constructor_type->structure) { + ai->constructor_type->structure->is_declaration = is_declaration; + exec_node *expr_node = ai->expressions.head; + + /* Iterate through the struct's fields' declarations. E.g., iterate from + * "float a, b" to "int c" in the struct below. + * + * struct { + * float a, b; + * int c; + * } s; + */ + for (exec_node *decl_list_node = + ai->constructor_type->structure->declarations.head; + !decl_list_node->is_tail_sentinel(); + decl_list_node = decl_list_node->next) { + ast_declarator_list *decl_list = exec_node_data(ast_declarator_list, + decl_list_node, link); + + for (exec_node *decl_node = decl_list->declarations.head; + !decl_node->is_tail_sentinel() && !expr_node->is_tail_sentinel(); + decl_node = decl_node->next, expr_node = expr_node->next) { + ast_declaration *decl = exec_node_data(ast_declaration, decl_node, + link); + ast_expression *expr = exec_node_data(ast_expression, expr_node, + link); + + bool is_array = decl_list->type->specifier->is_array; + ast_expression *array_size = decl_list->type->specifier->array_size; + + /* Recognize variable declarations with the bracketed size attached + * to the type rather than the variable name as arrays. E.g., + * + * float a[2]; + * float[2] b; + * + * are both arrays, but <a>'s array_size is decl->array_size, while + * <b>'s array_size is decl_list->type->specifier->array_size. + */ + if (!is_array) { + /* FINISHME: Update when ARB_array_of_arrays is supported. */ + is_array = decl->is_array; + array_size = decl->array_size; + } + + /* Declaration shadows the <type> parameter. */ + ast_type_specifier *type = + new(ctx) ast_type_specifier(decl_list->type->specifier, + is_array, array_size); + + if (expr->oper == ast_aggregate) + _mesa_ast_set_aggregate_type(type, expr, state); + } + } + } else { + /* If the aggregate is a matrix, set its columns' types. */ + const char *name; + const glsl_type *const constructor_type = + ai->constructor_type->glsl_type(&name, state); + + if (constructor_type->is_matrix()) { + for (exec_node *expr_node = ai->expressions.head; + !expr_node->is_tail_sentinel(); + expr_node = expr_node->next) { + ast_expression *expr = exec_node_data(ast_expression, expr_node, + link); + + /* Declaration shadows the <type> parameter. */ + ast_type_specifier *type = new(ctx) + ast_type_specifier(_mesa_ast_get_matrix_column_type_name(name)); + + if (expr->oper == ast_aggregate) + _mesa_ast_set_aggregate_type(type, expr, state); + } + } + } +} + + void _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q) { @@ -862,6 +1050,19 @@ ast_expression::print(void) const break; } + case ast_aggregate: { + printf("{ "); + foreach_list_const(n, & this->expressions) { + if (n != this->expressions.get_head()) + printf(", "); + + ast_node *ast = exec_node_data(ast_node, n, link); + ast->print(); + } + printf("} "); + break; + } + default: assert(0); break; @@ -959,7 +1160,7 @@ ast_declaration::print(void) const } -ast_declaration::ast_declaration(const char *identifier, int is_array, +ast_declaration::ast_declaration(const char *identifier, bool is_array, ast_expression *array_size, ast_expression *initializer) { @@ -1236,6 +1437,7 @@ ast_struct_specifier::ast_struct_specifier(const char *identifier, } name = identifier; this->declarations.push_degenerate_list_at_head(&declarator_list->link); + is_declaration = true; } extern "C" { diff --git a/mesalib/src/glsl/glsl_symbol_table.cpp b/mesalib/src/glsl/glsl_symbol_table.cpp index dcc3a1e02..f9c84e86e 100644 --- a/mesalib/src/glsl/glsl_symbol_table.cpp +++ b/mesalib/src/glsl/glsl_symbol_table.cpp @@ -88,17 +88,19 @@ public: } symbol_table_entry(ir_variable *v) : - v(v), f(0), t(0), ibu(0), ibi(0), ibo(0) {} + v(v), f(0), t(0), ibu(0), ibi(0), ibo(0), a(0) {} symbol_table_entry(ir_function *f) : - v(0), f(f), t(0), ibu(0), ibi(0), ibo(0) {} + v(0), f(f), t(0), ibu(0), ibi(0), ibo(0), a(0) {} symbol_table_entry(const glsl_type *t) : - v(0), f(0), t(t), ibu(0), ibi(0), ibo(0) {} + v(0), f(0), t(t), ibu(0), ibi(0), ibo(0), a(0) {} symbol_table_entry(const glsl_type *t, enum ir_variable_mode mode) : - v(0), f(0), t(0), ibu(0), ibi(0), ibo(0) + v(0), f(0), t(0), ibu(0), ibi(0), ibo(0), a(0) { assert(t->is_interface()); add_interface(t, mode); } + symbol_table_entry(const class ast_type_specifier *a): + v(0), f(0), t(0), ibu(0), ibi(0), ibo(0), a(a) {} ir_variable *v; ir_function *f; @@ -106,6 +108,7 @@ public: const glsl_type *ibu; const glsl_type *ibi; const glsl_type *ibo; + const class ast_type_specifier *a; }; glsl_symbol_table::glsl_symbol_table() @@ -176,6 +179,15 @@ bool glsl_symbol_table::add_type(const char *name, const glsl_type *t) return _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0; } +bool glsl_symbol_table::add_type_ast(const char *name, const class ast_type_specifier *a) +{ + symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(a); + char ast_name[strlen("#ast.") + strlen(name) + 1]; + strcpy(ast_name, "#ast."); + strcat(ast_name + strlen("#ast."), name); + return _mesa_symbol_table_add_symbol(table, -1, ast_name, entry) == 0; +} + bool glsl_symbol_table::add_interface(const char *name, const glsl_type *i, enum ir_variable_mode mode) { @@ -227,6 +239,15 @@ const glsl_type *glsl_symbol_table::get_type(const char *name) return entry != NULL ? entry->t : NULL; } +const class ast_type_specifier *glsl_symbol_table::get_type_ast(const char *name) +{ + char ast_name[strlen("#ast.") + strlen(name) + 1]; + strcpy(ast_name, "#ast."); + strcat(ast_name + strlen("#ast."), name); + symbol_table_entry *entry = get_entry(ast_name); + return entry != NULL ? entry->a : NULL; +} + const glsl_type *glsl_symbol_table::get_interface(const char *name, enum ir_variable_mode mode) { diff --git a/mesalib/src/glsl/glsl_symbol_table.h b/mesalib/src/glsl/glsl_symbol_table.h index 98084c990..46fd3fc5f 100644 --- a/mesalib/src/glsl/glsl_symbol_table.h +++ b/mesalib/src/glsl/glsl_symbol_table.h @@ -103,6 +103,7 @@ public: /*@{*/ bool add_variable(ir_variable *v); bool add_type(const char *name, const glsl_type *t); + bool add_type_ast(const char *name, const class ast_type_specifier *t); bool add_function(ir_function *f); bool add_interface(const char *name, const glsl_type *i, enum ir_variable_mode mode); @@ -119,6 +120,7 @@ public: /*@{*/ ir_variable *get_variable(const char *name); const glsl_type *get_type(const char *name); + const class ast_type_specifier *get_type_ast(const char *name); ir_function *get_function(const char *name); const glsl_type *get_interface(const char *name, enum ir_variable_mode mode); diff --git a/mesalib/src/glsl/opt_flip_matrices.cpp b/mesalib/src/glsl/opt_flip_matrices.cpp index 497513fe8..2107b1d47 100644 --- a/mesalib/src/glsl/opt_flip_matrices.cpp +++ b/mesalib/src/glsl/opt_flip_matrices.cpp @@ -81,8 +81,10 @@ matrix_flipper::visit_enter(ir_expression *ir) if (mvp_transpose && strcmp(mat_var->name, "gl_ModelViewProjectionMatrix") == 0) { +#ifndef NDEBUG ir_dereference_variable *deref = ir->operands[0]->as_dereference_variable(); assert(deref && deref->var == mat_var); +#endif void *mem_ctx = ralloc_parent(ir); |