* As a result, my preference is to put as little C code as possible in the
* parser (and lexer) sources.
*/
-#include <stdio.h>
+
#include "main/imports.h"
#include "glsl_symbol_table.h"
#include "glsl_parser_extras.h"
}
}
- ir_instruction *tmp = new ir_assignment(lhs, rhs, NULL);
- instructions->push_tail(tmp);
+ /* Most callers of do_assignment (assign, add_assign, pre_inc/dec,
+ * but not post_inc) need the converted assigned value as an rvalue
+ * to handle things like:
+ *
+ * i = j += 1;
+ *
+ * So we always just store the computed value being assigned to a
+ * temporary and return a deref of that temporary. If the rvalue
+ * ends up not being used, the temp will get copy-propagated out.
+ */
+ ir_variable *var = new ir_variable(rhs->type, "assignment_tmp");
+ instructions->push_tail(var);
+ instructions->push_tail(new ir_assignment(new ir_dereference_variable(var),
+ rhs,
+ NULL));
+
+ instructions->push_tail(new ir_assignment(lhs,
+ new ir_dereference_variable(var),
+ NULL));
- return rhs;
+ return new ir_dereference_variable(var);
}
static ir_rvalue *
-get_lvalue_copy(exec_list *instructions, struct _mesa_glsl_parse_state *state,
- ir_rvalue *lvalue, YYLTYPE loc)
+get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
{
ir_variable *var;
- ir_rvalue *var_deref;
/* FINISHME: Give unique names to the temporaries. */
- var = new ir_variable(lvalue->type, "_internal_tmp");
+ var = new ir_variable(lvalue->type, "_post_incdec_tmp");
var->mode = ir_var_auto;
- var_deref = new ir_dereference_variable(var);
- do_assignment(instructions, state, var_deref, lvalue, loc);
+ instructions->push_tail(new ir_assignment(new ir_dereference_variable(var),
+ lvalue, NULL));
/* Once we've created this temporary, mark it read only so it's no
* longer considered an lvalue.
*/
var->read_only = true;
- return var_deref;
+ return new ir_dereference_variable(var);
}
ir_rvalue *temp_rhs = new ir_expression(operations[this->oper], type,
op[0], op[1]);
- result = do_assignment(instructions, state, op[0], temp_rhs,
+ result = do_assignment(instructions, state,
+ (ir_rvalue *)op[0]->clone(NULL), temp_rhs,
this->subexpressions[0]->get_location());
type = result->type;
error_emitted = (op[0]->type->is_error());
temp_rhs = new ir_expression(operations[this->oper], type,
op[0], op[1]);
- result = do_assignment(instructions, state, op[0], temp_rhs,
+ result = do_assignment(instructions, state,
+ (ir_rvalue *)op[0]->clone(NULL), temp_rhs,
this->subexpressions[0]->get_location());
type = result->type;
error_emitted = type->is_error();
type = op[1]->type;
}
- ir_variable *const tmp = generate_temporary(type,
- instructions, state);
+ 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;
+ } else {
+ ir_variable *const tmp = generate_temporary(type,
+ instructions, state);
- ir_if *const stmt = new ir_if(op[0]);
- instructions->push_tail(stmt);
+ ir_if *const stmt = new ir_if(op[0]);
+ instructions->push_tail(stmt);
- then_instructions.move_nodes_to(& stmt->then_instructions);
- ir_dereference *const then_deref = new ir_dereference_variable(tmp);
- ir_assignment *const then_assign =
- new ir_assignment(then_deref, op[1], NULL);
- stmt->then_instructions.push_tail(then_assign);
+ then_instructions.move_nodes_to(& stmt->then_instructions);
+ ir_dereference *const then_deref = new ir_dereference_variable(tmp);
+ ir_assignment *const then_assign =
+ new ir_assignment(then_deref, op[1], NULL);
+ stmt->then_instructions.push_tail(then_assign);
- else_instructions.move_nodes_to(& stmt->else_instructions);
- ir_dereference *const else_deref = new ir_dereference_variable(tmp);
- ir_assignment *const else_assign =
- new ir_assignment(else_deref, op[2], NULL);
- stmt->else_instructions.push_tail(else_assign);
+ else_instructions.move_nodes_to(& stmt->else_instructions);
+ ir_dereference *const else_deref = new ir_dereference_variable(tmp);
+ ir_assignment *const else_assign =
+ new ir_assignment(else_deref, op[2], NULL);
+ stmt->else_instructions.push_tail(else_assign);
- result = new ir_dereference_variable(tmp);
+ result = new ir_dereference_variable(tmp);
+ }
break;
}
temp_rhs = new ir_expression(operations[this->oper], type,
op[0], op[1]);
- result = do_assignment(instructions, state, op[0], temp_rhs,
+ result = do_assignment(instructions, state,
+ (ir_rvalue *)op[0]->clone(NULL), temp_rhs,
this->subexpressions[0]->get_location());
type = result->type;
error_emitted = op[0]->type->is_error();
/* Get a temporary of a copy of the lvalue before it's modified.
* This may get thrown away later.
*/
- result = get_lvalue_copy(instructions, state, op[0],
- this->subexpressions[0]->get_location());
+ result = get_lvalue_copy(instructions, (ir_rvalue *)op[0]->clone(NULL));
- (void)do_assignment(instructions, state, op[0], temp_rhs,
+ (void)do_assignment(instructions, state,
+ (ir_rvalue *)op[0]->clone(NULL), temp_rhs,
this->subexpressions[0]->get_location());
type = result->type;
case ast_int_constant:
type = glsl_type::int_type;
- result = new ir_constant(type, & this->primary_expression);
+ result = new ir_constant(this->primary_expression.int_constant);
break;
case ast_uint_constant:
type = glsl_type::uint_type;
- result = new ir_constant(type, & this->primary_expression);
+ result = new ir_constant(this->primary_expression.uint_constant);
break;
case ast_float_constant:
type = glsl_type::float_type;
- result = new ir_constant(type, & this->primary_expression);
+ result = new ir_constant(this->primary_expression.float_constant);
break;
case ast_bool_constant:
type = glsl_type::bool_type;
- result = new ir_constant(type, & this->primary_expression);
+ result = new ir_constant(bool(this->primary_expression.bool_constant));
break;
case ast_sequence: {
if (qual->uniform)
var->shader_in = true;
- if (qual->varying) {
- if (qual->in)
+
+ /* Any 'in' or 'inout' variables at global scope must be marked as being
+ * shader inputs. Likewise, any 'out' or 'inout' variables at global scope
+ * must be marked as being shader outputs.
+ */
+ if (state->current_function == NULL) {
+ switch (var->mode) {
+ case ir_var_in:
+ case ir_var_uniform:
+ var->shader_in = true;
+ break;
+ case ir_var_out:
+ var->shader_out = true;
+ break;
+ case ir_var_inout:
var->shader_in = true;
- if (qual->out)
var->shader_out = true;
+ break;
+ default:
+ break;
+ }
}
if (qual->flat)
ir_dereference *const lhs = new ir_dereference_variable(var);
ir_rvalue *rhs = decl->initializer->hir(instructions, state);
- /* Calculate the constant value if this is a const
+ /* Calculate the constant value if this is a const or uniform
* declaration.
*/
- if (this->type->qualifier.constant) {
+ if (this->type->qualifier.constant || this->type->qualifier.uniform) {
ir_constant *constant_value = rhs->constant_expression_value();
if (!constant_value) {
_mesa_glsl_error(& initializer_loc, state,
- "initializer of const variable `%s' must be a "
+ "initializer of %s variable `%s' must be a "
"constant expression",
+ (this->type->qualifier.constant)
+ ? "const" : "uniform",
decl->identifier);
} else {
rhs = constant_value;
bool temp = var->read_only;
if (this->type->qualifier.constant)
var->read_only = false;
- result = do_assignment(instructions, state, lhs, rhs,
- this->get_location());
+
+ /* Never emit code to initialize a uniform.
+ */
+ if (!this->type->qualifier.uniform)
+ result = do_assignment(instructions, state, lhs, rhs,
+ this->get_location());
var->read_only = temp;
}
}
if (loop != NULL) {
ir_loop_jump *const jump =
- new ir_loop_jump(loop,
- (mode == ast_break)
+ new ir_loop_jump((mode == ast_break)
? ir_loop_jump::jump_break
: ir_loop_jump::jump_continue);
instructions->push_tail(jump);
ir_if *const if_stmt = new ir_if(not_cond);
ir_jump *const break_stmt =
- new ir_loop_jump(stmt, ir_loop_jump::jump_break);
+ new ir_loop_jump(ir_loop_jump::jump_break);
if_stmt->then_instructions.push_tail(break_stmt);
stmt->body_instructions.push_tail(if_stmt);