var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
ir_var_temporary);
instructions->push_tail(var);
- var->data.mode = ir_var_auto;
instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
lvalue));
}
ir_constant *cond_val = op[0]->constant_expression_value();
- ir_constant *then_val = op[1]->constant_expression_value();
- ir_constant *else_val = op[2]->constant_expression_value();
if (then_instructions.is_empty()
&& else_instructions.is_empty()
- && (cond_val != NULL) && (then_val != NULL) && (else_val != NULL)) {
- result = (cond_val->value.b[0]) ? then_val : else_val;
+ && cond_val != NULL) {
+ result = cond_val->value.b[0] ? op[1] : op[2];
} else {
ir_variable *const tmp =
new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary);
/* If there is no qualifier that changes the mode of the variable, leave
* the setting alone.
*/
+ assert(var->data.mode != ir_var_temporary);
if (qual->flags.q.in && qual->flags.q.out)
var->data.mode = ir_var_function_inout;
else if (qual->flags.q.in)
}
}
+static bool
+precision_qualifier_allowed(const glsl_type *type)
+{
+ /* Precision qualifiers apply to floating point, integer and sampler
+ * types.
+ *
+ * Section 4.5.2 (Precision Qualifiers) of the GLSL 1.30 spec says:
+ * "Any floating point or any integer declaration can have the type
+ * preceded by one of these precision qualifiers [...] Literal
+ * constants do not have precision qualifiers. Neither do Boolean
+ * variables.
+ *
+ * Section 4.5 (Precision and Precision Qualifiers) of the GLSL 1.30
+ * spec also says:
+ *
+ * "Precision qualifiers are added for code portability with OpenGL
+ * ES, not for functionality. They have the same syntax as in OpenGL
+ * ES."
+ *
+ * Section 8 (Built-In Functions) of the GLSL ES 1.00 spec says:
+ *
+ * "uniform lowp sampler2D sampler;
+ * highp vec2 coord;
+ * ...
+ * lowp vec4 col = texture2D (sampler, coord);
+ * // texture2D returns lowp"
+ *
+ * From this, we infer that GLSL 1.30 (and later) should allow precision
+ * qualifiers on sampler types just like float and integer types.
+ */
+ return type->is_float()
+ || type->is_integer()
+ || type->is_record()
+ || type->is_sampler();
+}
ir_rvalue *
ast_declarator_list::hir(exec_list *instructions,
}
- /* Precision qualifiers apply to floating point, integer and sampler
- * types.
- *
- * Section 4.5.2 (Precision Qualifiers) of the GLSL 1.30 spec says:
- * "Any floating point or any integer declaration can have the type
- * preceded by one of these precision qualifiers [...] Literal
- * constants do not have precision qualifiers. Neither do Boolean
- * variables.
- *
- * Section 4.5 (Precision and Precision Qualifiers) of the GLSL 1.30
- * spec also says:
- *
- * "Precision qualifiers are added for code portability with OpenGL
- * ES, not for functionality. They have the same syntax as in OpenGL
- * ES."
- *
- * Section 8 (Built-In Functions) of the GLSL ES 1.00 spec says:
- *
- * "uniform lowp sampler2D sampler;
- * highp vec2 coord;
- * ...
- * lowp vec4 col = texture2D (sampler, coord);
- * // texture2D returns lowp"
- *
- * From this, we infer that GLSL 1.30 (and later) should allow precision
- * qualifiers on sampler types just like float and integer types.
+ /* If a precision qualifier is allowed on a type, it is allowed on
+ * an array of that type.
*/
- if (this->type->qualifier.precision != ast_precision_none
- && !var->type->is_float()
- && !var->type->is_integer()
- && !var->type->is_record()
- && !var->type->is_sampler()
- && !(var->type->is_array()
- && (var->type->fields.array->is_float()
- || var->type->fields.array->is_integer()))) {
+ if (!(this->type->qualifier.precision == ast_precision_none
+ || precision_qualifier_allowed(var->type)
+ || (var->type->is_array()
+ && precision_qualifier_allowed(var->type->fields.array)))) {
_mesa_glsl_error(&loc, state,
"precision qualifiers apply only to floating point"
earlier->data.how_declared == ir_var_declared_in_block) {
_mesa_glsl_error(&loc, state,
"`%s' has already been redeclared using "
- "gl_PerVertex", var->name);
+ "gl_PerVertex", earlier->name);
}
earlier->data.how_declared = ir_var_declared_normally;
}
* loop.
*/
if (state->loop_nesting_ast != NULL &&
- mode == ast_continue) {
+ mode == ast_continue && !state->switch_state.is_switch_innermost) {
if (state->loop_nesting_ast->rest_expression) {
state->loop_nesting_ast->rest_expression->hir(instructions,
state);
}
if (state->switch_state.is_switch_innermost &&
+ mode == ast_continue) {
+ /* Set 'continue_inside' to true. */
+ ir_rvalue *const true_val = new (ctx) ir_constant(true);
+ ir_dereference_variable *deref_continue_inside_var =
+ new(ctx) ir_dereference_variable(state->switch_state.continue_inside);
+ instructions->push_tail(new(ctx) ir_assignment(deref_continue_inside_var,
+ true_val));
+
+ /* Break out from the switch, continue for the loop will
+ * be called right after switch. */
+ ir_loop_jump *const jump =
+ new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
+ instructions->push_tail(jump);
+
+ } else if (state->switch_state.is_switch_innermost &&
mode == ast_break) {
- /* Force break out of switch by setting is_break switch state.
- */
- ir_variable *const is_break_var = state->switch_state.is_break_var;
- ir_dereference_variable *const deref_is_break_var =
- new(ctx) ir_dereference_variable(is_break_var);
- ir_constant *const true_val = new(ctx) ir_constant(true);
- ir_assignment *const set_break_var =
- new(ctx) ir_assignment(deref_is_break_var, true_val);
-
- instructions->push_tail(set_break_var);
- }
- else {
+ /* Force break out of switch by inserting a break. */
+ ir_loop_jump *const jump =
+ new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
+ instructions->push_tail(jump);
+ } else {
ir_loop_jump *const jump =
new(ctx) ir_loop_jump((mode == ast_break)
? ir_loop_jump::jump_break
instructions->push_tail(new(ctx) ir_assignment(deref_is_fallthru_var,
is_fallthru_val));
- /* Initalize is_break state to false.
+ /* Initialize continue_inside state to false.
*/
- ir_rvalue *const is_break_val = new (ctx) ir_constant(false);
- state->switch_state.is_break_var =
+ state->switch_state.continue_inside =
new(ctx) ir_variable(glsl_type::bool_type,
- "switch_is_break_tmp",
+ "continue_inside_tmp",
ir_var_temporary);
- instructions->push_tail(state->switch_state.is_break_var);
+ instructions->push_tail(state->switch_state.continue_inside);
- ir_dereference_variable *deref_is_break_var =
- new(ctx) ir_dereference_variable(state->switch_state.is_break_var);
- instructions->push_tail(new(ctx) ir_assignment(deref_is_break_var,
- is_break_val));
+ ir_rvalue *const false_val = new (ctx) ir_constant(false);
+ ir_dereference_variable *deref_continue_inside_var =
+ new(ctx) ir_dereference_variable(state->switch_state.continue_inside);
+ instructions->push_tail(new(ctx) ir_assignment(deref_continue_inside_var,
+ false_val));
state->switch_state.run_default =
new(ctx) ir_variable(glsl_type::bool_type,
ir_var_temporary);
instructions->push_tail(state->switch_state.run_default);
+ /* Loop around the switch is used for flow control. */
+ ir_loop * loop = new(ctx) ir_loop();
+ instructions->push_tail(loop);
+
/* Cache test expression.
*/
- test_to_hir(instructions, state);
+ test_to_hir(&loop->body_instructions, state);
/* Emit code for body of switch stmt.
*/
- body->hir(instructions, state);
+ body->hir(&loop->body_instructions, state);
+
+ /* Insert a break at the end to exit loop. */
+ ir_loop_jump *jump = new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
+ loop->body_instructions.push_tail(jump);
+
+ /* If we are inside loop, check if continue got called inside switch. */
+ if (state->loop_nesting_ast != NULL) {
+ ir_dereference_variable *deref_continue_inside =
+ new(ctx) ir_dereference_variable(state->switch_state.continue_inside);
+ ir_if *irif = new(ctx) ir_if(deref_continue_inside);
+ ir_loop_jump *jump = new(ctx) ir_loop_jump(ir_loop_jump::jump_continue);
+
+ if (state->loop_nesting_ast != NULL) {
+ if (state->loop_nesting_ast->rest_expression) {
+ state->loop_nesting_ast->rest_expression->hir(&irif->then_instructions,
+ state);
+ }
+ if (state->loop_nesting_ast->mode ==
+ ast_iteration_statement::ast_do_while) {
+ state->loop_nesting_ast->condition_to_hir(&irif->then_instructions, state);
+ }
+ }
+ irif->then_instructions.push_tail(jump);
+ instructions->push_tail(irif);
+ }
hash_table_dtor(state->switch_state.labels_ht);
{
labels->hir(instructions, state);
- /* Conditionally set fallthru state based on break state. */
- ir_constant *const false_val = new(state) ir_constant(false);
- ir_dereference_variable *const deref_is_fallthru_var =
- new(state) ir_dereference_variable(state->switch_state.is_fallthru_var);
- ir_dereference_variable *const deref_is_break_var =
- new(state) ir_dereference_variable(state->switch_state.is_break_var);
- ir_assignment *const reset_fallthru_on_break =
- new(state) ir_assignment(deref_is_fallthru_var,
- false_val,
- deref_is_break_var);
- instructions->push_tail(reset_fallthru_on_break);
-
/* Guard case statements depending on fallthru state. */
ir_dereference_variable *const deref_fallthru_guard =
new(state) ir_dereference_variable(state->switch_state.is_fallthru_var);
*/
ir_variable *const junk =
new(state) ir_variable(type, "#default precision",
- ir_var_temporary);
+ ir_var_auto);
state->symbols->add_variable(junk);
}
"members");
}
+ if (qual->flags.q.constant) {
+ YYLTYPE loc = decl_list->get_location();
+ _mesa_glsl_error(&loc, state,
+ "const storage qualifier cannot be applied "
+ "to struct or interface block members");
+ }
+
field_type = process_array_type(&loc, decl_type,
decl->array_specifier, state);
fields[i].type = field_type;
{
YYLTYPE loc = this->get_location();
+ /* Interface blocks must be declared at global scope */
+ if (state->current_function != NULL) {
+ _mesa_glsl_error(&loc, state,
+ "Interface block `%s' must be declared "
+ "at global scope",
+ this->block_name);
+ }
+
/* The ast_interface_block has a list of ast_declarator_lists. We
* need to turn those into ir_variables with an association
* with this uniform block.
state->struct_specifier_depth--;
- if (!redeclaring_per_vertex)
+ if (!redeclaring_per_vertex) {
validate_identifier(this->block_name, loc, state);
+ /* From section 4.3.9 ("Interface Blocks") of the GLSL 4.50 spec:
+ *
+ * "Block names have no other use within a shader beyond interface
+ * matching; it is a compile-time error to use a block name at global
+ * scope for anything other than as a block name."
+ */
+ ir_variable *var = state->symbols->get_variable(this->block_name);
+ if (var && !var->type->is_interface()) {
+ _mesa_glsl_error(&loc, state, "Block name `%s' is "
+ "already used in the scope.",
+ this->block_name);
+ }
+ }
+
const glsl_type *earlier_per_vertex = NULL;
if (redeclaring_per_vertex) {
/* Find the previous declaration of gl_PerVertex. If we're redeclaring
}
if (this->instance_name != NULL) {
_mesa_glsl_error(&loc, state,
- "gl_PerVertex input may not be redeclared with "
+ "gl_PerVertex output may not be redeclared with "
"an instance name");
}
break;
var->data.stream = this->layout.stream;
+ /* Examine var name here since var may get deleted in the next call */
+ bool var_is_gl_id = is_gl_identifier(var->name);
+
if (redeclaring_per_vertex) {
ir_variable *earlier =
get_variable_being_redeclared(var, loc, state,
true /* allow_all_redeclarations */);
- if (!is_gl_identifier(var->name) || earlier == NULL) {
+ if (!var_is_gl_id || earlier == NULL) {
_mesa_glsl_error(&loc, state,
"redeclaration of gl_PerVertex can only "
"include built-in variables");
} else if (earlier->data.how_declared == ir_var_declared_normally) {
_mesa_glsl_error(&loc, state,
- "`%s' has already been redeclared", var->name);
+ "`%s' has already been redeclared",
+ earlier->name);
} else {
earlier->data.how_declared = ir_var_declared_in_block;
earlier->reinit_interface_type(block_type);
* declare it earlier).
*/
ir_variable *var = new(state->symbols)
- ir_variable(glsl_type::ivec3_type, "gl_WorkGroupSize", ir_var_auto);
+ ir_variable(glsl_type::uvec3_type, "gl_WorkGroupSize", ir_var_auto);
var->data.how_declared = ir_var_declared_implicitly;
var->data.read_only = true;
instructions->push_tail(var);
ir_constant_data data;
memset(&data, 0, sizeof(data));
for (int i = 0; i < 3; i++)
- data.i[i] = this->local_size[i];
- var->constant_value = new(var) ir_constant(glsl_type::ivec3_type, &data);
+ data.u[i] = this->local_size[i];
+ var->constant_value = new(var) ir_constant(glsl_type::uvec3_type, &data);
var->constant_initializer =
- new(var) ir_constant(glsl_type::ivec3_type, &data);
+ new(var) ir_constant(glsl_type::uvec3_type, &data);
var->data.has_initializer = true;
return NULL;