{
void *ctx = state;
bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
+ ir_rvalue *extract_channel = NULL;
/* If the assignment LHS comes back as an ir_binop_vector_extract
* expression, move it to the RHS as an ir_triop_vector_insert.
*/
if (lhs->ir_type == ir_type_expression) {
- ir_expression *const expr = lhs->as_expression();
+ ir_expression *const lhs_expr = lhs->as_expression();
- if (unlikely(expr->operation == ir_binop_vector_extract)) {
+ if (unlikely(lhs_expr->operation == ir_binop_vector_extract)) {
ir_rvalue *new_rhs =
validate_assignment(state, lhs_loc, lhs->type,
rhs, is_initializer);
if (new_rhs == NULL) {
return lhs;
} else {
+ /* This converts:
+ * - LHS: (expression float vector_extract <vec> <channel>)
+ * - RHS: <scalar>
+ * into:
+ * - LHS: <vec>
+ * - RHS: (expression vec2 vector_insert <vec> <channel> <scalar>)
+ *
+ * The LHS type is now a vector instead of a scalar. Since GLSL
+ * allows assignments to be used as rvalues, we need to re-extract
+ * the channel from assignment_temp when returning the rvalue.
+ */
+ extract_channel = lhs_expr->operands[1];
rhs = new(ctx) ir_expression(ir_triop_vector_insert,
- expr->operands[0]->type,
- expr->operands[0],
+ lhs_expr->operands[0]->type,
+ lhs_expr->operands[0],
new_rhs,
- expr->operands[1]);
- lhs = expr->operands[0]->clone(ctx, NULL);
+ extract_channel);
+ lhs = lhs_expr->operands[0]->clone(ctx, NULL);
}
}
}
if (!error_emitted)
instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var));
+ if (extract_channel) {
+ return new(ctx) ir_expression(ir_binop_vector_extract,
+ new(ctx) ir_dereference_variable(var),
+ extract_channel->clone(ctx, NULL));
+ }
return new(ctx) ir_dereference_variable(var);
}
fail = true;
break;
+
+ case MESA_SHADER_COMPUTE:
+ _mesa_glsl_error(loc, state,
+ "compute shader variables cannot be given "
+ "explicit locations");
+ return;
};
if (fail) {
if (var->data.mode == ir_var_shader_in)
var->data.invariant = true;
break;
+ case MESA_SHADER_COMPUTE:
+ /* Invariance isn't meaningful in compute shaders. */
+ break;
}
}
}
foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
- assert(!decl->is_array);
assert(decl->array_specifier == NULL);
assert(decl->initializer == NULL);
_mesa_glsl_error(& loc, state,
"break may only appear in a loop or a switch");
} else {
- /* For a loop, inline the for loop expression again,
- * since we don't know where near the end of
- * the loop body the normal copy of it
- * is going to be placed.
+ /* For a loop, inline the for loop expression again, since we don't
+ * know where near the end of the loop body the normal copy of it is
+ * going to be placed. Same goes for the condition for a do-while
+ * loop.
*/
if (state->loop_nesting_ast != NULL &&
- mode == ast_continue &&
- state->loop_nesting_ast->rest_expression) {
- state->loop_nesting_ast->rest_expression->hir(instructions,
- state);
- }
+ mode == ast_continue) {
+ if (state->loop_nesting_ast->rest_expression) {
+ state->loop_nesting_ast->rest_expression->hir(instructions,
+ state);
+ }
+ if (state->loop_nesting_ast->mode ==
+ ast_iteration_statement::ast_do_while) {
+ state->loop_nesting_ast->condition_to_hir(instructions, state);
+ }
+ }
if (state->switch_state.is_switch_innermost &&
mode == ast_break) {
}
void
-ast_iteration_statement::condition_to_hir(ir_loop *stmt,
+ast_iteration_statement::condition_to_hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
{
void *ctx = state;
if (condition != NULL) {
ir_rvalue *const cond =
- condition->hir(& stmt->body_instructions, state);
+ condition->hir(instructions, state);
if ((cond == NULL)
|| !cond->type->is_boolean() || !cond->type->is_scalar()) {
new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
if_stmt->then_instructions.push_tail(break_stmt);
- stmt->body_instructions.push_tail(if_stmt);
+ instructions->push_tail(if_stmt);
}
}
}
state->switch_state.is_switch_innermost = false;
if (mode != ast_do_while)
- condition_to_hir(stmt, state);
+ condition_to_hir(&stmt->body_instructions, state);
if (body != NULL)
body->hir(& stmt->body_instructions, state);
rest_expression->hir(& stmt->body_instructions, state);
if (mode == ast_do_while)
- condition_to_hir(stmt, state);
+ condition_to_hir(&stmt->body_instructions, state);
if (mode != ast_do_while)
state->symbols->pop_scope();
return NULL;
}
- if (this->is_array) {
+ if (this->array_specifier != NULL) {
_mesa_glsl_error(&loc, state,
"default precision statements do not apply to "
"arrays");
_mesa_shader_stage_to_string(state->stage));
}
if (this->instance_name == NULL ||
- strcmp(this->instance_name, "gl_in") != 0 || !this->is_array) {
+ strcmp(this->instance_name, "gl_in") != 0 || this->array_specifier == NULL) {
_mesa_glsl_error(&loc, state,
"gl_PerVertex input must be redeclared as "
"gl_in[]");
* variable (or input block, see interface blocks below) needs to be
* declared as an array.
*/
- if (state->stage == MESA_SHADER_GEOMETRY && !this->is_array &&
+ if (state->stage == MESA_SHADER_GEOMETRY && this->array_specifier == NULL &&
var_mode == ir_var_shader_in) {
_mesa_glsl_error(&loc, state, "geometry shader inputs must be arrays");
}
ir_variable *var;
- if (this->is_array) {
+ if (this->array_specifier != NULL) {
/* Section 4.3.7 (Interface Blocks) of the GLSL 1.50 spec says:
*
* For uniform blocks declared an array, each individual array
/* In order to have an array size, the block must also be declared with
* an instane name.
*/
- assert(!this->is_array);
+ assert(this->array_specifier == NULL);
for (unsigned i = 0; i < num_variables; i++) {
ir_variable *var =