aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2013-07-12 08:25:37 +0200
committermarha <marha@users.sourceforge.net>2013-07-12 08:25:37 +0200
commit66b46719d55e60d53b42858770d6ac40d079ab13 (patch)
treeaad06d011ed8b820685f72ada34e56ee0f2580c6 /mesalib/src/glsl
parentf8f0209a691e0d0838d1ef9d602ebacafee2a233 (diff)
parentffce4319c2fb6f4f663cc5a9660e1d5837fcde87 (diff)
downloadvcxsrv-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.h70
-rw-r--r--mesalib/src/glsl/ast_function.cpp275
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp20
-rw-r--r--mesalib/src/glsl/ast_type.cpp3
-rw-r--r--mesalib/src/glsl/builtin_compiler/Makefile.am3
-rw-r--r--mesalib/src/glsl/glsl_lexer.ll4
-rw-r--r--mesalib/src/glsl/glsl_parser.yy60
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp204
-rw-r--r--mesalib/src/glsl/glsl_symbol_table.cpp29
-rw-r--r--mesalib/src/glsl/glsl_symbol_table.h2
-rw-r--r--mesalib/src/glsl/opt_flip_matrices.cpp2
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);