class ir_instruction : public exec_node {
public:
enum ir_node_type ir_type;
- const struct glsl_type *type;
+
+ /**
+ * GCC 4.7+ and clang warn when deleting an ir_instruction unless
+ * there's a virtual destructor present. Because we almost
+ * universally use ralloc for our memory management of
+ * ir_instructions, the destructor doesn't need to do any work.
+ */
+ virtual ~ir_instruction()
+ {
+ }
/** ir_print_visitor helper for debugging. */
void print(void) const;
ir_instruction()
{
ir_type = ir_type_unset;
- type = NULL;
}
};
+/**
+ * The base class for all "values"/expression trees.
+ */
class ir_rvalue : public ir_instruction {
public:
- virtual ir_rvalue *clone(void *mem_ctx, struct hash_table *) const = 0;
+ const struct glsl_type *type;
+
+ virtual ir_rvalue *clone(void *mem_ctx, struct hash_table *) const;
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- virtual ir_constant *constant_expression_value() = 0;
+ virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
virtual ir_rvalue * as_rvalue()
{
* for vector and scalar types that have all elements set to the value
* zero (or \c false for booleans).
*
- * \sa ir_constant::has_value, ir_rvalue::is_one, ir_rvalue::is_negative_one
+ * \sa ir_constant::has_value, ir_rvalue::is_one, ir_rvalue::is_negative_one,
+ * ir_constant::is_basis
*/
virtual bool is_zero() const;
* for vector and scalar types that have all elements set to the value
* one (or \c true for booleans).
*
- * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_negative_one
+ * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_negative_one,
+ * ir_constant::is_basis
*/
virtual bool is_one() const;
* The base implementation of this function always returns \c false. The
* \c ir_constant class over-rides this function to return \c true \b only
* for vector and scalar types that have all elements set to the value
- * negative one. For boolean times, the result is always \c false.
+ * negative one. For boolean types, the result is always \c false.
*
* \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_one
+ * ir_constant::is_basis
*/
virtual bool is_negative_one() const;
+ /**
+ * Determine if an r-value is a basis vector
+ *
+ * The base implementation of this function always returns \c false. The
+ * \c ir_constant class over-rides this function to return \c true \b only
+ * for vector and scalar types that have one element set to the value one,
+ * and the other elements set to the value zero. For boolean types, the
+ * result is always \c false.
+ *
+ * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_one,
+ * is_constant::is_negative_one
+ */
+ virtual bool is_basis() const;
+
+
+ /**
+ * Return a generic value of error_type.
+ *
+ * Allocation will be performed with 'mem_ctx' as ralloc owner.
+ */
+ static ir_rvalue *error_value(void *mem_ctx);
+
protected:
ir_rvalue();
};
glsl_interp_qualifier determine_interpolation_mode(bool flat_shade);
/**
- * Delcared name of the variable
+ * Declared type of the variable
+ */
+ const struct glsl_type *type;
+
+ /**
+ * Declared name of the variable
*/
const char *name;
* Several GLSL semantic checks require knowledge of whether or not a
* variable has been used. For example, it is an error to redeclare a
* variable as invariant after it has been used.
+ *
+ * This is only maintained in the ast_to_hir.cpp path, not in
+ * Mesa's fixed function or ARB program paths.
*/
unsigned used:1;
+ /**
+ * Has this variable been statically assigned?
+ *
+ * This answers whether the variable was assigned in any path of
+ * the shader during ast_to_hir. This doesn't answer whether it is
+ * still written after dead code removal, nor is it maintained in
+ * non-ast_to_hir.cpp (GLSL parsing) paths.
+ */
+ unsigned assigned:1;
+
/**
* Storage class of the variable.
*
unsigned pixel_center_integer:1;
/*@}*/
- /**
- * \brief Layout qualifier for gl_FragDepth.
- *
- * This is not equal to \c ir_depth_layout_none if and only if this
- * variable is \c gl_FragDepth and a layout qualifier is specified.
- */
- ir_depth_layout depth_layout;
-
/**
* Was the location explicitly set in the shader?
*
* no effect).
*/
unsigned explicit_location:1;
+ unsigned explicit_index:1;
+
+ /**
+ * Does this variable have an initializer?
+ *
+ * This is used by the linker to cross-validiate initializers of global
+ * variables.
+ */
+ unsigned has_initializer:1;
+
+ /**
+ * \brief Layout qualifier for gl_FragDepth.
+ *
+ * This is not equal to \c ir_depth_layout_none if and only if this
+ * variable is \c gl_FragDepth and a layout qualifier is specified.
+ */
+ ir_depth_layout depth_layout;
/**
* Storage location of the base of this variable
* - Vertex shader output: one of the values from \c gl_vert_result.
* - Fragment shader input: one of the values from \c gl_frag_attrib.
* - Fragment shader output: one of the values from \c gl_frag_result.
- * - Uniforms: Per-stage uniform slot number.
+ * - Uniforms: Per-stage uniform slot number for default uniform block.
+ * - Uniforms: Index within the uniform block definition for UBO members.
* - Other: This field is not currently used.
*
* If the variable is a uniform, shader input, or shader output, and the
*/
int location;
+ /**
+ * Uniform block number for uniforms.
+ *
+ * This index is into the shader's list of uniform blocks, not the
+ * linked program's merged list.
+ *
+ * If the variable is not in a uniform block, the value will be -1.
+ */
+ int uniform_block;
+
+ /**
+ * output index for dual source blending.
+ */
+ int index;
+
/**
* Built-in state that backs this uniform
*
* Value assigned in the initializer of a variable declared "const"
*/
ir_constant *constant_value;
+
+ /**
+ * Constant expression assigned in the initializer of the variable
+ *
+ * \warning
+ * This field and \c ::constant_value are distinct. Even if the two fields
+ * refer to constants with the same value, they must point to separate
+ * objects.
+ */
+ ir_constant *constant_initializer;
};
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+ /**
+ * Attempt to evaluate this function as a constant expression,
+ * given a list of the actual parameters and the variable context.
+ * Returns NULL for non-built-ins.
+ */
+ ir_constant *constant_expression_value(exec_list *actual_parameters, struct hash_table *variable_context);
+
/**
* Get the name of the function for which this is a signature
*/
/** Function of which this signature is one overload. */
class ir_function *_function;
+ /** Function signature of which this one is a prototype clone */
+ const ir_function_signature *origin;
+
friend class ir_function;
+
+ /**
+ * Helper function to run a list of instructions for constant
+ * expression evaluation.
+ *
+ * The hash table represents the values of the visible variables.
+ * There are no scoping issues because the table is indexed on
+ * ir_variable pointers, not variable names.
+ *
+ * Returns false if the expression is not constant, true otherwise,
+ * and the value in *result if result is non-NULL.
+ */
+ bool constant_expression_evaluate_expression_list(const struct exec_list &body,
+ struct hash_table *variable_context,
+ ir_constant **result);
};
return signatures.iterator();
}
+ /**
+ * Find a signature that matches a set of actual parameters, taking implicit
+ * conversions into account. Also flags whether the match was exact.
+ */
+ ir_function_signature *matching_signature(const exec_list *actual_param,
+ bool *match_is_exact);
+
/**
* Find a signature that matches a set of actual parameters, taking implicit
* conversions into account.
virtual ir_assignment *clone(void *mem_ctx, struct hash_table *ht) const;
- virtual ir_constant *constant_expression_value();
+ virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
virtual void accept(ir_visitor *v)
{
ir_unop_rcp,
ir_unop_rsq,
ir_unop_sqrt,
- ir_unop_exp, /**< Log base e on gentype */
- ir_unop_log, /**< Natural log on gentype */
+ ir_unop_exp, /**< Log base e on gentype */
+ ir_unop_log, /**< Natural log on gentype */
ir_unop_exp2,
ir_unop_log2,
- ir_unop_f2i, /**< Float-to-integer conversion. */
- ir_unop_i2f, /**< Integer-to-float conversion. */
- ir_unop_f2b, /**< Float-to-boolean conversion */
- ir_unop_b2f, /**< Boolean-to-float conversion */
- ir_unop_i2b, /**< int-to-boolean conversion */
- ir_unop_b2i, /**< Boolean-to-int conversion */
- ir_unop_u2f, /**< Unsigned-to-float conversion. */
- ir_unop_i2u, /**< Integer-to-unsigned conversion. */
- ir_unop_u2i, /**< Unsigned-to-integer conversion. */
+ ir_unop_f2i, /**< Float-to-integer conversion. */
+ ir_unop_f2u, /**< Float-to-unsigned conversion. */
+ ir_unop_i2f, /**< Integer-to-float conversion. */
+ ir_unop_f2b, /**< Float-to-boolean conversion */
+ ir_unop_b2f, /**< Boolean-to-float conversion */
+ ir_unop_i2b, /**< int-to-boolean conversion */
+ ir_unop_b2i, /**< Boolean-to-int conversion */
+ ir_unop_u2f, /**< Unsigned-to-float conversion. */
+ ir_unop_i2u, /**< Integer-to-unsigned conversion. */
+ ir_unop_u2i, /**< Unsigned-to-integer conversion. */
+ ir_unop_bitcast_i2f, /**< Bit-identical int-to-float "conversion" */
+ ir_unop_bitcast_f2i, /**< Bit-identical float-to-int "conversion" */
+ ir_unop_bitcast_u2f, /**< Bit-identical uint-to-float "conversion" */
+ ir_unop_bitcast_f2u, /**< Bit-identical float-to-uint "conversion" */
ir_unop_any,
/**
ir_binop_pow,
+ /**
+ * Load a value the size of a given GLSL type from a uniform block.
+ *
+ * operand0 is the ir_constant uniform block index in the linked shader.
+ * operand1 is a byte offset within the uniform block.
+ */
+ ir_binop_ubo_load,
+
/**
* A sentinel marking the last of the binary operations.
*/
- ir_last_binop = ir_binop_pow,
+ ir_last_binop = ir_binop_ubo_load,
ir_quadop_vector,
/**
* A sentinel marking the last of all operations.
*/
- ir_last_opcode = ir_last_binop
+ ir_last_opcode = ir_quadop_vector
};
class ir_expression : public ir_rvalue {
/**
* Attempt to constant-fold the expression
*
+ * The "variable_context" hash table links ir_variable * to ir_constant *
+ * that represent the variables' values. \c NULL represents an empty
+ * context.
+ *
* If the expression cannot be constant folded, this method will return
* \c NULL.
*/
- virtual ir_constant *constant_expression_value();
+ virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
/**
* Determine the number of operands used by an expression
/**
- * IR instruction representing a function call
+ * HIR instruction representing a high-level function call, containing a list
+ * of parameters and returning a value in the supplied temporary.
*/
-class ir_call : public ir_rvalue {
+class ir_call : public ir_instruction {
public:
- ir_call(ir_function_signature *callee, exec_list *actual_parameters)
- : callee(callee)
+ ir_call(ir_function_signature *callee,
+ ir_dereference_variable *return_deref,
+ exec_list *actual_parameters)
+ : return_deref(return_deref), callee(callee)
{
ir_type = ir_type_call;
assert(callee->return_type != NULL);
- type = callee->return_type;
actual_parameters->move_nodes_to(& this->actual_parameters);
this->use_builtin = callee->is_builtin;
}
virtual ir_call *clone(void *mem_ctx, struct hash_table *ht) const;
- virtual ir_constant *constant_expression_value();
+ virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
virtual ir_call *as_call()
{
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- /**
- * Get a generic ir_call object when an error occurs
- *
- * Any allocation will be performed with 'ctx' as ralloc owner.
- */
- static ir_call *get_error_instruction(void *ctx);
-
/**
* Get an iterator for the set of acutal parameters
*/
}
/**
- * Get the function signature bound to this function call
+ * Generates an inline version of the function before @ir,
+ * storing the return value in return_deref.
*/
- ir_function_signature *get_callee()
- {
- return callee;
- }
+ void generate_inline(ir_instruction *ir);
/**
- * Set the function call target
+ * Storage for the function's return value.
+ * This must be NULL if the return type is void.
*/
- void set_callee(ir_function_signature *sig);
+ ir_dereference_variable *return_deref;
/**
- * Generates an inline version of the function before @ir,
- * returning the return value of the function.
+ * The specific function signature being called.
*/
- ir_rvalue *generate_inline(ir_instruction *ir);
+ ir_function_signature *callee;
/* List of ir_rvalue of paramaters passed in this call. */
exec_list actual_parameters;
/** Should this call only bind to a built-in function? */
bool use_builtin;
-
-private:
- ir_call()
- : callee(NULL)
- {
- this->ir_type = ir_type_call;
- }
-
- ir_function_signature *callee;
};
{
this->ir_type = ir_type_loop_jump;
this->mode = mode;
- this->loop = loop;
}
virtual ir_loop_jump *clone(void *mem_ctx, struct hash_table *) const;
/** Mode selector for the jump instruction. */
enum jump_mode mode;
-private:
- /** Loop containing this break instruction. */
- ir_loop *loop;
};
/**
class ir_texture : public ir_rvalue {
public:
ir_texture(enum ir_texture_opcode op)
- : op(op), projector(NULL), shadow_comparitor(NULL), offset(NULL)
+ : op(op), coordinate(NULL), projector(NULL), shadow_comparitor(NULL),
+ offset(NULL)
{
this->ir_type = ir_type_texture;
}
virtual ir_texture *clone(void *mem_ctx, struct hash_table *) const;
- virtual ir_constant *constant_expression_value();
+ virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
virtual void accept(ir_visitor *v)
{
virtual ir_swizzle *clone(void *mem_ctx, struct hash_table *) const;
- virtual ir_constant *constant_expression_value();
+ virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
virtual ir_swizzle *as_swizzle()
{
* Get the variable that is ultimately referenced by an r-value
*/
virtual ir_variable *variable_referenced() const = 0;
+
+ /**
+ * Get the constant that is ultimately referenced by an r-value,
+ * in a constant expression evaluation context.
+ *
+ * The offset is used when the reference is to a specific column of
+ * a matrix.
+ */
+ virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const = 0;
};
virtual ir_dereference_variable *clone(void *mem_ctx,
struct hash_table *) const;
- virtual ir_constant *constant_expression_value();
+ virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
virtual ir_dereference_variable *as_dereference_variable()
{
return this->var;
}
+ /**
+ * Get the constant that is ultimately referenced by an r-value,
+ * in a constant expression evaluation context.
+ *
+ * The offset is used when the reference is to a specific column of
+ * a matrix.
+ */
+ virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
+
virtual ir_variable *whole_variable_referenced()
{
/* ir_dereference_variable objects always dereference the entire
virtual ir_dereference_array *clone(void *mem_ctx,
struct hash_table *) const;
- virtual ir_constant *constant_expression_value();
+ virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
virtual ir_dereference_array *as_dereference_array()
{
return this->array->variable_referenced();
}
+ /**
+ * Get the constant that is ultimately referenced by an r-value,
+ * in a constant expression evaluation context.
+ *
+ * The offset is used when the reference is to a specific column of
+ * a matrix.
+ */
+ virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
+
virtual void accept(ir_visitor *v)
{
v->visit(this);
virtual ir_dereference_record *clone(void *mem_ctx,
struct hash_table *) const;
- virtual ir_constant *constant_expression_value();
+ virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
/**
* Get the variable that is ultimately referenced by an r-value
return this->record->variable_referenced();
}
+ /**
+ * Get the constant that is ultimately referenced by an r-value,
+ * in a constant expression evaluation context.
+ *
+ * The offset is used when the reference is to a specific column of
+ * a matrix.
+ */
+ virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
+
virtual void accept(ir_visitor *v)
{
v->visit(this);
virtual ir_constant *clone(void *mem_ctx, struct hash_table *) const;
- virtual ir_constant *constant_expression_value();
+ virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
virtual ir_constant *as_constant()
{
ir_constant *get_record_field(const char *name);
+ /**
+ * Copy the values on another constant at a given offset.
+ *
+ * The offset is ignored for array or struct copies, it's only for
+ * scalars or vectors into vectors or matrices.
+ *
+ * With identical types on both sides and zero offset it's clone()
+ * without creating a new object.
+ */
+
+ void copy_offset(ir_constant *src, int offset);
+
+ /**
+ * Copy the values on another constant at a given offset and
+ * following an assign-like mask.
+ *
+ * The mask is ignored for scalars.
+ *
+ * Note that this function only handles what assign can handle,
+ * i.e. at most a vector as source and a column of a matrix as
+ * destination.
+ */
+
+ void copy_masked_offset(ir_constant *src, int offset, unsigned int mask);
+
/**
* Determine whether a constant has the same value as another constant
*
* \sa ir_constant::is_zero, ir_constant::is_one,
- * ir_constant::is_negative_one
+ * ir_constant::is_negative_one, ir_constant::is_basis
*/
bool has_value(const ir_constant *) const;
virtual bool is_zero() const;
virtual bool is_one() const;
virtual bool is_negative_one() const;
+ virtual bool is_basis() const;
/**
* Value of the constant.