[Mesa-dev] [PATCH 4/9] glsl: Add array specifier to ast code
Timothy Arceri
t_arceri at yahoo.com.au
Wed Jan 15 22:27:25 PST 2014
Signed-off-by: Timothy Arceri <t_arceri at yahoo.com.au>
---
src/glsl/ast.h | 45 +++++++----
src/glsl/ast_array_index.cpp | 13 +++
src/glsl/ast_to_hir.cpp | 173 +++++++++++++++++++++++++++-------------
src/glsl/ast_type.cpp | 8 +-
src/glsl/glsl_parser_extras.cpp | 30 +++----
src/glsl/glsl_parser_extras.h | 2 +
6 files changed, 179 insertions(+), 92 deletions(-)
diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index 76911f0..bbae9cd 100644
--- a/src/glsl/ast.h
+++ b/src/glsl/ast.h
@@ -276,6 +276,21 @@ private:
bool cons;
};
+class ast_array_specifier : public ast_node {
+public:
+ ast_array_specifier()
+ : ast_node()
+ {
+ dimension_count = 1;
+ }
+
+ virtual void print(void) const;
+
+ unsigned dimension_count;
+ bool is_unsized_array;
+ exec_list array_dimensions;
+};
+
/**
* C-style aggregate initialization class
*
@@ -325,14 +340,15 @@ public:
class ast_declaration : public ast_node {
public:
- ast_declaration(const char *identifier, bool is_array, ast_expression *array_size,
- ast_expression *initializer);
+ ast_declaration(const char *identifier, bool is_array,
+ ast_array_specifier *array_specifier,
+ ast_expression *initializer);
virtual void print(void) const;
const char *identifier;
bool is_array;
- ast_expression *array_size;
+ ast_array_specifier *array_specifier;
ast_expression *initializer;
};
@@ -531,7 +547,6 @@ public:
};
-
class ast_type_specifier : public ast_node {
public:
/**
@@ -542,9 +557,9 @@ public:
* 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_array_specifier *array_specifier)
: ast_node(), type_name(that->type_name), structure(that->structure),
- is_array(is_array), array_size(array_size),
+ is_array(is_array), array_specifier(array_specifier),
default_precision(that->default_precision)
{
/* empty */
@@ -553,7 +568,7 @@ public:
/** Construct a type specifier from a type name */
ast_type_specifier(const char *name)
: type_name(name), structure(NULL),
- is_array(false), array_size(NULL),
+ is_array(false), array_specifier(NULL),
default_precision(ast_precision_none)
{
/* empty */
@@ -562,7 +577,7 @@ public:
/** Construct a type specifier from a structure definition */
ast_type_specifier(ast_struct_specifier *s)
: type_name(s->name), structure(s),
- is_array(false), array_size(NULL),
+ is_array(false), array_specifier(NULL),
default_precision(ast_precision_none)
{
/* empty */
@@ -580,7 +595,7 @@ public:
ast_struct_specifier *structure;
bool is_array;
- ast_expression *array_size;
+ ast_array_specifier *array_specifier;
/** For precision statements, this is the given precision; otherwise none. */
unsigned default_precision:2;
@@ -634,7 +649,7 @@ public:
type(NULL),
identifier(NULL),
is_array(false),
- array_size(NULL),
+ array_specifier(NULL),
formal_parameter(false),
is_void(false)
{
@@ -649,7 +664,7 @@ public:
ast_fully_specified_type *type;
const char *identifier;
bool is_array;
- ast_expression *array_size;
+ ast_array_specifier *array_specifier;
static void parameters_to_hir(exec_list *ast_parameters,
bool formal, exec_list *ir_parameters,
@@ -897,12 +912,12 @@ public:
ast_interface_block(ast_type_qualifier layout,
const char *instance_name,
bool is_array,
- ast_expression *array_size)
+ ast_array_specifier *array_specifier)
: layout(layout), block_name(NULL), instance_name(instance_name),
- is_array(is_array), array_size(array_size)
+ is_array(is_array), array_specifier(array_specifier)
{
if (!is_array)
- assert(array_size == NULL);
+ assert(array_specifier == NULL);
}
virtual ir_rvalue *hir(exec_list *instructions,
@@ -937,7 +952,7 @@ public:
* If the block is not declared as an array or if the block instance array
* is unsized, this field will be \c NULL.
*/
- ast_expression *array_size;
+ ast_array_specifier *array_specifier;
};
diff --git a/src/glsl/ast_array_index.cpp b/src/glsl/ast_array_index.cpp
index a5f2320..f3b060e 100644
--- a/src/glsl/ast_array_index.cpp
+++ b/src/glsl/ast_array_index.cpp
@@ -25,6 +25,19 @@
#include "glsl_types.h"
#include "ir.h"
+void
+ast_array_specifier::print(void) const
+{
+ if (this->is_unsized_array) {
+ printf("[ ] ");
+ }
+
+ foreach_list_typed (ast_node, array_dimension, link, &this->array_dimensions) {
+ printf("[ ");
+ array_dimension->print();
+ printf("] ");
+ }
+}
/**
* If \c ir is a reference to an array for which we are tracking the max array
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 4cc8eb1..c0e3443 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -1771,67 +1771,131 @@ ast_compound_statement::hir(exec_list *instructions,
return NULL;
}
+static const unsigned
+process_array_size(exec_node *node,
+ struct _mesa_glsl_parse_state *state)
+{
+ int result = 0;
+ exec_list dummy_instructions;
+
+ ast_node *array_size = exec_node_data(ast_node, node, link);
+ ir_rvalue *const ir = array_size->hir(& dummy_instructions,
+ state);
+ YYLTYPE loc = array_size->get_location();
+
+ if (ir != NULL) {
+ if (!ir->type->is_integer()) {
+ _mesa_glsl_error(& loc, state,
+ "array size must be integer type");
+ } else if (!ir->type->is_scalar()) {
+ _mesa_glsl_error(& loc, state,
+ "array size must be scalar type");
+ } else {
+ ir_constant *const size = ir->constant_expression_value();
+
+ if (size == NULL) {
+ _mesa_glsl_error(& loc, state, "array size must be a "
+ "constant valued expression");
+ } else if (size->value.i[0] <= 0) {
+ _mesa_glsl_error(& loc, state, "array size must be > 0");
+ } else {
+ assert(size->type == ir->type);
+ result = size->value.u[0];
+
+ /* 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 result;
+}
static const glsl_type *
-process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size,
- struct _mesa_glsl_parse_state *state)
+process_array_type(YYLTYPE *loc, const glsl_type *base,
+ ast_array_specifier *array_specifier,
+ struct _mesa_glsl_parse_state *state)
{
- unsigned length = 0;
+ const glsl_type *array_type = NULL;
+ const glsl_type *element_type = base;
+ const glsl_type *array_type_temp = element_type;
+
+ unsigned outer_dimension_count = 0;
+ unsigned dimension_count = 1;
if (base == NULL)
return glsl_type::error_type;
- /* From page 19 (page 25) of the GLSL 1.20 spec:
- *
- * "Only one-dimensional arrays may be declared."
- */
if (base->is_array()) {
- _mesa_glsl_error(loc, state,
- "invalid array of `%s' (only one-dimensional arrays "
- "may be declared)",
- base->name);
- return glsl_type::error_type;
+
+ /* From page 19 (page 25) of the GLSL 1.20 spec:
+ *
+ * "Only one-dimensional arrays may be declared."
+ */
+ if (!state->ARB_arrays_of_arrays_enable) {
+ _mesa_glsl_error(loc, state,
+ "invalid array of `%s'"
+ "#version 120 / GL_ARB_arrays_of_arrays "
+ "required for defining arrays of arrays",
+ base->name);
+ return glsl_type::error_type;
+ }
+
+ if (base->length == 0) {
+ _mesa_glsl_error(loc, state,
+ "only the outermost array dimension can "
+ "be unsized",
+ base->name);
+ return glsl_type::error_type;
+ }
+
+ /* Settings these variables will cause
+ * any array dimensions processed with the base type to
+ * be appended onto the end of the array
+ */
+ outer_dimension_count = base->dimension_count;
+ dimension_count = base->dimension_count + 1;
+ element_type = base->element_type();
}
- if (array_size != NULL) {
- exec_list dummy_instructions;
- ir_rvalue *const ir = array_size->hir(& dummy_instructions, state);
- YYLTYPE loc = array_size->get_location();
+ if (array_specifier != NULL) {
- if (ir != NULL) {
- if (!ir->type->is_integer()) {
- _mesa_glsl_error(& loc, state, "array size must be integer type");
- } else if (!ir->type->is_scalar()) {
- _mesa_glsl_error(& loc, state, "array size must be scalar type");
- } else {
- ir_constant *const size = ir->constant_expression_value();
-
- if (size == NULL) {
- _mesa_glsl_error(& loc, state, "array size must be a "
- "constant valued expression");
- } else if (size->value.i[0] <= 0) {
- _mesa_glsl_error(& loc, state, "array size must be > 0");
- } else {
- assert(size->type == ir->type);
- length = size->value.u[0];
-
- /* 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());
- }
- }
+ exec_node *node = array_specifier->array_dimensions.tail_pred;
+ outer_dimension_count += array_specifier->dimension_count;
+
+ unsigned array_size;
+ for (/* nothing */; !node->is_head_sentinel(); node = node->prev) {
+ array_size = process_array_size(node, state);
+ array_type_temp = glsl_type::get_array_instance(array_type_temp,
+ array_size,
+ dimension_count);
+ dimension_count++;
+ }
+
+ if (array_specifier->is_unsized_array) {
+ array_type_temp = glsl_type::get_array_instance(array_type_temp,
+ 0,
+ dimension_count);
+ }
+
+ if (array_type_temp == element_type) {
+ /* we found no array sizes */
+ array_type = NULL;
+ } else {
+ array_type = array_type_temp;
}
}
- const glsl_type *array_type = glsl_type::get_array_instance(base, length);
+ /* make sure the ast count and the current count match */
+ assert(dimension_count == outer_dimension_count);
+
return array_type != NULL ? array_type : glsl_type::error_type;
}
-
const glsl_type *
ast_type_specifier::glsl_type(const char **name,
struct _mesa_glsl_parse_state *state) const
@@ -1843,7 +1907,7 @@ ast_type_specifier::glsl_type(const char **name,
if (this->is_array) {
YYLTYPE loc = this->get_location();
- type = process_array_type(&loc, type, this->array_size, state);
+ type = process_array_type(&loc, type, this->array_specifier, state);
}
return type;
@@ -2824,7 +2888,7 @@ ast_declarator_list::hir(exec_list *instructions,
foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
assert(!decl->is_array);
- assert(decl->array_size == NULL);
+ assert(decl->array_specifier == NULL);
assert(decl->initializer == NULL);
ir_variable *const earlier =
@@ -2960,7 +3024,7 @@ ast_declarator_list::hir(exec_list *instructions,
}
if (decl->is_array) {
- var_type = process_array_type(&loc, decl_type, decl->array_size,
+ var_type = process_array_type(&loc, decl_type, decl->array_specifier,
state);
if (var_type->is_error())
continue;
@@ -3524,7 +3588,7 @@ ast_parameter_declarator::hir(exec_list *instructions,
* call already handled the "vec4[..] foo" case.
*/
if (this->is_array) {
- type = process_array_type(&loc, type, this->array_size, state);
+ type = process_array_type(&loc, type, this->array_specifier, state);
}
if (!type->is_error() && type->is_unsized_array()) {
@@ -4654,8 +4718,8 @@ ast_process_structure_or_interface_block(exec_list *instructions,
}
if (decl->is_array) {
- field_type = process_array_type(&loc, decl_type, decl->array_size,
- state);
+ field_type = process_array_type(&loc, decl_type,
+ decl->array_specifier, state);
}
fields[i].type = field_type;
fields[i].name = decl->identifier;
@@ -5019,6 +5083,10 @@ ast_interface_block::hir(exec_list *instructions,
ir_variable *var;
if (this->is_array) {
+
+ 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
@@ -5038,7 +5106,7 @@ ast_interface_block::hir(exec_list *instructions,
* interface array size *doesn't* need to be specified is on a
* geometry shader input.
*/
- if (this->array_size == NULL &&
+ if (block_array_type->is_unsized_array() &&
(state->stage != MESA_SHADER_GEOMETRY || !this->layout.flags.q.in)) {
_mesa_glsl_error(&loc, state,
"only geometry shader inputs may be unsized "
@@ -5046,9 +5114,6 @@ ast_interface_block::hir(exec_list *instructions,
}
- const glsl_type *block_array_type =
- process_array_type(&loc, block_type, this->array_size, state);
-
var = new(state) ir_variable(block_array_type,
this->instance_name,
var_mode);
diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp
index d758bfa..ac48597 100644
--- a/src/glsl/ast_type.cpp
+++ b/src/glsl/ast_type.cpp
@@ -33,13 +33,9 @@ ast_type_specifier::print(void) const
}
if (is_array) {
- printf("[ ");
-
- if (array_size) {
- array_size->print();
+ if (array_specifier) {
+ array_specifier->print();
}
-
- printf("] ");
}
}
diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
index 21dc3ab..92076b5 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -484,6 +484,7 @@ struct _mesa_glsl_extension {
static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
/* API availability */
/* name GL ES supported flag */
+ EXT(ARB_arrays_of_arrays, true, false, ARB_arrays_of_arrays),
EXT(ARB_conservative_depth, true, false, ARB_conservative_depth),
EXT(ARB_draw_buffers, true, false, dummy_true),
EXT(ARB_draw_instanced, true, false, ARB_draw_instanced),
@@ -769,7 +770,7 @@ _mesa_ast_set_aggregate_type(const ast_type_specifier *type,
link);
bool is_array = decl_list->type->specifier->is_array;
- ast_expression *array_size = decl_list->type->specifier->array_size;
+ ast_array_specifier *array_specifier = decl_list->type->specifier->array_specifier;
/* Recognize variable declarations with the bracketed size attached
* to the type rather than the variable name as arrays. E.g.,
@@ -777,19 +778,18 @@ _mesa_ast_set_aggregate_type(const ast_type_specifier *type,
* 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.
+ * are both arrays, but <a>'s array_specifier is decl->array_specifier, while
+ * <b>'s array_specifier is decl_list->type->specifier->array_specifier.
*/
if (!is_array) {
- /* FINISHME: Update when ARB_array_of_arrays is supported. */
is_array = decl->is_array;
- array_size = decl->array_size;
+ array_specifier = decl->array_specifier;
}
/* Declaration shadows the <type> parameter. */
ast_type_specifier *type =
new(ctx) ast_type_specifier(decl_list->type->specifier,
- is_array, array_size);
+ is_array, array_specifier);
if (expr->oper == ast_aggregate)
_mesa_ast_set_aggregate_type(type, expr, state);
@@ -876,15 +876,11 @@ ast_node::ast_node(void)
static void
-ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
+ast_opt_array_dimensions_print(bool is_array, const ast_array_specifier *array_specifier)
{
if (is_array) {
- printf("[ ");
-
- if (array_size)
- array_size->print();
-
- printf("] ");
+ if (array_specifier)
+ array_specifier->print();
}
}
@@ -1108,7 +1104,7 @@ ast_parameter_declarator::print(void) const
type->print();
if (identifier)
printf("%s ", identifier);
- ast_opt_array_size_print(is_array, array_size);
+ ast_opt_array_dimensions_print(is_array, array_specifier);
}
@@ -1124,7 +1120,7 @@ void
ast_declaration::print(void) const
{
printf("%s ", identifier);
- ast_opt_array_size_print(is_array, array_size);
+ ast_opt_array_dimensions_print(is_array, array_specifier);
if (initializer) {
printf("= ");
@@ -1134,12 +1130,12 @@ ast_declaration::print(void) const
ast_declaration::ast_declaration(const char *identifier, bool is_array,
- ast_expression *array_size,
+ ast_array_specifier *array_specifier,
ast_expression *initializer)
{
this->identifier = identifier;
this->is_array = is_array;
- this->array_size = array_size;
+ this->array_specifier = array_specifier;
this->initializer = initializer;
}
diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h
index 2444a96..1478f00 100644
--- a/src/glsl/glsl_parser_extras.h
+++ b/src/glsl/glsl_parser_extras.h
@@ -294,6 +294,8 @@ struct _mesa_glsl_parse_state {
* \name Enable bits for GLSL extensions
*/
/*@{*/
+ bool ARB_arrays_of_arrays_enable;
+ bool ARB_arrays_of_arrays_warn;
bool ARB_draw_buffers_enable;
bool ARB_draw_buffers_warn;
bool ARB_draw_instanced_enable;
--
1.8.3.1
More information about the mesa-dev
mailing list