summaryrefslogtreecommitdiffstats
path: root/src/glsl/ast_to_hir.cpp
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2011-03-04 15:29:33 -0800
committerIan Romanick <[email protected]>2011-03-04 16:32:37 -0800
commit0292ffb85c03e9fa15b9395e3875109dd8979292 (patch)
treed902c13434f267460686f3d36bc47a75665ef5e2 /src/glsl/ast_to_hir.cpp
parent8e6cb9fe51a2237e51b47198eb7d46b14ad288b5 (diff)
glsl: Refactor AST-to-HIR code handling variable initializers
Diffstat (limited to 'src/glsl/ast_to_hir.cpp')
-rw-r--r--src/glsl/ast_to_hir.cpp233
1 files changed, 125 insertions, 108 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 8864279e5d6..0074ed2bd44 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -2187,6 +2187,129 @@ get_variable_being_redeclared(ir_variable *var, ast_declaration *decl,
return earlier;
}
+/**
+ * Generate the IR for an initializer in a variable declaration
+ */
+ir_rvalue *
+process_initializer(ir_variable *var, ast_declaration *decl,
+ ast_fully_specified_type *type,
+ exec_list *initializer_instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ ir_rvalue *result = NULL;
+
+ YYLTYPE initializer_loc = decl->initializer->get_location();
+
+ /* From page 24 (page 30 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "All uniform variables are read-only and are initialized either
+ * directly by an application via API commands, or indirectly by
+ * OpenGL."
+ */
+ if ((state->language_version <= 110)
+ && (var->mode == ir_var_uniform)) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "cannot initialize uniforms in GLSL 1.10");
+ }
+
+ if (var->type->is_sampler()) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "cannot initialize samplers");
+ }
+
+ if ((var->mode == ir_var_in) && (state->current_function == NULL)) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "cannot initialize %s shader input / %s",
+ _mesa_glsl_shader_target_name(state->target),
+ (state->target == vertex_shader)
+ ? "attribute" : "varying");
+ }
+
+ ir_dereference *const lhs = new(state) ir_dereference_variable(var);
+ ir_rvalue *rhs = decl->initializer->hir(initializer_instructions,
+ state);
+
+ /* Calculate the constant value if this is a const or uniform
+ * declaration.
+ */
+ if (type->qualifier.flags.q.constant
+ || type->qualifier.flags.q.uniform) {
+ ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs);
+ if (new_rhs != NULL) {
+ rhs = new_rhs;
+
+ ir_constant *constant_value = rhs->constant_expression_value();
+ if (!constant_value) {
+ _mesa_glsl_error(& initializer_loc, state,
+ "initializer of %s variable `%s' must be a "
+ "constant expression",
+ (type->qualifier.flags.q.constant)
+ ? "const" : "uniform",
+ decl->identifier);
+ if (var->type->is_numeric()) {
+ /* Reduce cascading errors. */
+ var->constant_value = ir_constant::zero(state, var->type);
+ }
+ } else {
+ rhs = constant_value;
+ var->constant_value = constant_value;
+ }
+ } else {
+ _mesa_glsl_error(&initializer_loc, state,
+ "initializer of type %s cannot be assigned to "
+ "variable of type %s",
+ rhs->type->name, var->type->name);
+ if (var->type->is_numeric()) {
+ /* Reduce cascading errors. */
+ var->constant_value = ir_constant::zero(state, var->type);
+ }
+ }
+ }
+
+ if (rhs && !rhs->type->is_error()) {
+ bool temp = var->read_only;
+ if (type->qualifier.flags.q.constant)
+ var->read_only = false;
+
+ /* Never emit code to initialize a uniform.
+ */
+ const glsl_type *initializer_type;
+ if (!type->qualifier.flags.q.uniform) {
+ result = do_assignment(initializer_instructions, state,
+ lhs, rhs,
+ type->get_location());
+ initializer_type = result->type;
+ } else
+ initializer_type = rhs->type;
+
+ /* If the declared variable is an unsized array, it must inherrit
+ * its full type from the initializer. A declaration such as
+ *
+ * uniform float a[] = float[](1.0, 2.0, 3.0, 3.0);
+ *
+ * becomes
+ *
+ * uniform float a[4] = float[](1.0, 2.0, 3.0, 3.0);
+ *
+ * The assignment generated in the if-statement (below) will also
+ * automatically handle this case for non-uniforms.
+ *
+ * If the declared variable is not an array, the types must
+ * already match exactly. As a result, the type assignment
+ * here can be done unconditionally. For non-uniforms the call
+ * to do_assignment can change the type of the initializer (via
+ * the implicit conversion rules). For uniforms the initializer
+ * must be a constant expression, and the type of that expression
+ * was validated above.
+ */
+ var->type = initializer_type;
+
+ var->read_only = temp;
+ }
+
+ return result;
+}
+
ir_rvalue *
ast_declarator_list::hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
@@ -2571,114 +2694,8 @@ ast_declarator_list::hir(exec_list *instructions,
*/
exec_list initializer_instructions;
if (decl->initializer != NULL) {
- YYLTYPE initializer_loc = decl->initializer->get_location();
-
- /* From page 24 (page 30 of the PDF) of the GLSL 1.10 spec:
- *
- * "All uniform variables are read-only and are initialized either
- * directly by an application via API commands, or indirectly by
- * OpenGL."
- */
- if ((state->language_version <= 110)
- && (var->mode == ir_var_uniform)) {
- _mesa_glsl_error(& initializer_loc, state,
- "cannot initialize uniforms in GLSL 1.10");
- }
-
- if (var->type->is_sampler()) {
- _mesa_glsl_error(& initializer_loc, state,
- "cannot initialize samplers");
- }
-
- if ((var->mode == ir_var_in) && (state->current_function == NULL)) {
- _mesa_glsl_error(& initializer_loc, state,
- "cannot initialize %s shader input / %s",
- _mesa_glsl_shader_target_name(state->target),
- (state->target == vertex_shader)
- ? "attribute" : "varying");
- }
-
- ir_dereference *const lhs = new(ctx) ir_dereference_variable(var);
- ir_rvalue *rhs = decl->initializer->hir(&initializer_instructions,
- state);
-
- /* Calculate the constant value if this is a const or uniform
- * declaration.
- */
- if (this->type->qualifier.flags.q.constant
- || this->type->qualifier.flags.q.uniform) {
- ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs);
- if (new_rhs != NULL) {
- rhs = new_rhs;
-
- ir_constant *constant_value = rhs->constant_expression_value();
- if (!constant_value) {
- _mesa_glsl_error(& initializer_loc, state,
- "initializer of %s variable `%s' must be a "
- "constant expression",
- (this->type->qualifier.flags.q.constant)
- ? "const" : "uniform",
- decl->identifier);
- if (var->type->is_numeric()) {
- /* Reduce cascading errors. */
- var->constant_value = ir_constant::zero(ctx, var->type);
- }
- } else {
- rhs = constant_value;
- var->constant_value = constant_value;
- }
- } else {
- _mesa_glsl_error(&initializer_loc, state,
- "initializer of type %s cannot be assigned to "
- "variable of type %s",
- rhs->type->name, var->type->name);
- if (var->type->is_numeric()) {
- /* Reduce cascading errors. */
- var->constant_value = ir_constant::zero(ctx, var->type);
- }
- }
- }
-
- if (rhs && !rhs->type->is_error()) {
- bool temp = var->read_only;
- if (this->type->qualifier.flags.q.constant)
- var->read_only = false;
-
- /* Never emit code to initialize a uniform.
- */
- const glsl_type *initializer_type;
- if (!this->type->qualifier.flags.q.uniform) {
- result = do_assignment(&initializer_instructions, state,
- lhs, rhs,
- this->get_location());
- initializer_type = result->type;
- } else
- initializer_type = rhs->type;
-
- /* If the declared variable is an unsized array, it must inherrit
- * its full type from the initializer. A declaration such as
- *
- * uniform float a[] = float[](1.0, 2.0, 3.0, 3.0);
- *
- * becomes
- *
- * uniform float a[4] = float[](1.0, 2.0, 3.0, 3.0);
- *
- * The assignment generated in the if-statement (below) will also
- * automatically handle this case for non-uniforms.
- *
- * If the declared variable is not an array, the types must
- * already match exactly. As a result, the type assignment
- * here can be done unconditionally. For non-uniforms the call
- * to do_assignment can change the type of the initializer (via
- * the implicit conversion rules). For uniforms the initializer
- * must be a constant expression, and the type of that expression
- * was validated above.
- */
- var->type = initializer_type;
-
- var->read_only = temp;
- }
+ result = process_initializer(var, decl, this->type,
+ &initializer_instructions, state);
}
/* From page 23 (page 29 of the PDF) of the GLSL 1.10 spec: