summaryrefslogtreecommitdiffstats
path: root/src/glsl/glsl_parser_extras.cpp
diff options
context:
space:
mode:
authorPaul Berry <stereotype441@gmail.com>2014-01-21 15:41:26 -0800
committerPaul Berry <stereotype441@gmail.com>2014-01-22 11:08:30 -0800
commit0da1a2cc369052643ccaea75a1722cc37652d82a (patch)
treee85839b80332c2280671c376d16719ec43a1c823 /src/glsl/glsl_parser_extras.cpp
parent6ec210989fa10847091f06fcfcab77dd07618dff (diff)
downloadexternal_mesa3d-0da1a2cc369052643ccaea75a1722cc37652d82a.zip
external_mesa3d-0da1a2cc369052643ccaea75a1722cc37652d82a.tar.gz
external_mesa3d-0da1a2cc369052643ccaea75a1722cc37652d82a.tar.bz2
glsl: Simplify aggregate type inference to prepare for ARB_arrays_of_arrays.
Most of the time it is not necessary to perform type inference to compile GLSL; the type of every expression can be inferred from the contents of the expression itself (and previous type declarations). The exception is aggregate initializers: their type is determined by the LHS of the variable being assigned to. For example, in the statement: mat2 foo = { { 1, 2 }, { 3, 4 } }; the type of { 1, 2 } is only known to be vec2 (as opposed to, say, ivec2, uvec2, int[2], or a struct) because of the fact that the result is being assigned to a mat2. Previous to this patch, we handled this situation by doing some type inference during parsing: when parsing a declaration like the one above, we would call _mesa_set_aggregate_type(), which would infer the type of each aggregate initializer and store it in the corresponding ast_aggregate_initializer::constructor_type field. Since this happened at parse time, we couldn't do the type inference using glsl_type objects; we had to use ast_type_specifiers, which are much more awkward to work with. Things are about to get more complicated when we add support for ARB_arrays_of_arrays. This patch simplifies things by postponing the call to _mesa_set_aggregate_type() until ast-to-hir time, when we have access to glsl_type objects. As a side benefit, we only need to have one call to _mesa_set_aggregate_type() now, instead of six. Reviewed-by: Matt Turner <mattst88@gmail.com>
Diffstat (limited to 'src/glsl/glsl_parser_extras.cpp')
-rw-r--r--src/glsl/glsl_parser_extras.cpp136
1 files changed, 24 insertions, 112 deletions
diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
index 9a1e0a2..345e426 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -635,25 +635,6 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
/**
- * 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
@@ -700,37 +681,19 @@ _mesa_ast_get_matrix_column_type_name(const char *matrix_type_name)
* 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)
+_mesa_ast_set_aggregate_type(const glsl_type *type,
+ ast_expression *expr)
{
- 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;
- }
+ ai->constructor_type = type;
/* 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.
+ if (type->is_array()) {
+ /* Each array element has the type type->element_type().
*
* 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) {
@@ -738,84 +701,33 @@ _mesa_ast_set_aggregate_type(const ast_type_specifier *type,
link);
if (expr->oper == ast_aggregate)
- _mesa_ast_set_aggregate_type(non_array_type, expr, state);
+ _mesa_ast_set_aggregate_type(type->element_type(), expr);
}
/* 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;
+ } else if (type->is_record()) {
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);
+ /* Iterate through the struct's fields. */
+ for (unsigned i = 0; !expr_node->is_tail_sentinel() && i < type->length;
+ i++, 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(type, expr, state);
+ if (expr->oper == ast_aggregate) {
+ _mesa_ast_set_aggregate_type(type->fields.structure[i].type, expr);
}
}
- } 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);
- }
+ /* If the aggregate is a matrix, set its columns' types. */
+ } else if (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);
+
+ if (expr->oper == ast_aggregate)
+ _mesa_ast_set_aggregate_type(type->column_type(), expr);
}
}
}