#ifndef IR_H
#define IR_H
+#include <cstdio>
+#include <cstdlib>
+
#include "list.h"
#include "ir_visitor.h"
#include "ir_hierarchical_visitor.h"
const struct glsl_type *type;
class ir_constant *constant_expression_value();
+
+ /** ir_print_visitor helper for debugging. */
+ void print(void);
+
virtual void accept(ir_visitor *) = 0;
virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0;
virtual class ir_variable * as_variable() { return NULL; }
virtual class ir_function * as_function() { return NULL; }
virtual class ir_dereference * as_dereference() { return NULL; }
+ virtual class ir_dereference_array * as_dereference_array() { return NULL; }
virtual class ir_rvalue * as_rvalue() { return NULL; }
- virtual class ir_label * as_label() { return NULL; }
virtual class ir_loop * as_loop() { return NULL; }
virtual class ir_assignment * as_assignment() { return NULL; }
virtual class ir_call * as_call() { return NULL; }
return NULL;
}
+
+ /**
+ * If an r-value is a reference to a whole variable, get that variable
+ *
+ * \return
+ * Pointer to a variable that is completely dereferenced by the r-value. If
+ * the r-value is not a dereference or the dereference does not access the
+ * entire variable (i.e., it's just one array element, struct field), \c NULL
+ * is returned.
+ */
+ virtual ir_variable *whole_variable_referenced()
+ {
+ return NULL;
+ }
+
protected:
ir_rvalue()
{
return var;
}
+ /**
+ * Get the string value for the interpolation qualifier
+ *
+ * \return
+ * If none of \c shader_in or \c shader_out is set, an empty string will
+ * be returned. Otherwise the string that would be used in a shader to
+ * specify \c mode will be returned.
+ */
+ const char *interpolation_string() const;
+
const char *name;
/**
ir_unop_cos,
/*@}*/
+ /**
+ * \name Partial derivatives.
+ */
+ /*@{*/
+ ir_unop_dFdx,
+ ir_unop_dFdy,
+ /*@}*/
+
ir_binop_add,
ir_binop_sub,
ir_binop_mul,
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
-private:
ir_rvalue *value;
};
/*@}*/
+/**
+ * Texture sampling opcodes used in ir_texture
+ */
+enum ir_texture_opcode {
+ ir_tex, /* Regular texture look-up */
+ ir_txb, /* Texture look-up with LOD bias */
+ ir_txl, /* Texture look-up with explicit LOD */
+ ir_txd, /* Texture look-up with partial derivatvies */
+ ir_txf /* Texel fetch with explicit LOD */
+};
+
+
+/**
+ * IR instruction to sample a texture
+ *
+ * The specific form of the IR instruction depends on the \c mode value
+ * selected from \c ir_texture_opcodes. In the printed IR, these will
+ * appear as:
+ *
+ * Texel offset
+ * | Projection divisor
+ * | | Shadow comparitor
+ * | | |
+ * v v v
+ * (tex (sampler) (coordinate) (0 0 0) (1) ( ))
+ * (txb (sampler) (coordinate) (0 0 0) (1) ( ) (bias))
+ * (txl (sampler) (coordinate) (0 0 0) (1) ( ) (lod))
+ * (txd (sampler) (coordinate) (0 0 0) (1) ( ) (dPdx dPdy))
+ * (txf (sampler) (coordinate) (0 0 0) (lod))
+ */
+class ir_texture : public ir_rvalue {
+public:
+ ir_texture(enum ir_texture_opcode op)
+ : op(op), projector(NULL), shadow_comparitor(NULL)
+ {
+ /* empty */
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /**
+ * Return a string representing the ir_texture_opcode.
+ */
+ const char *opcode_string();
+
+ /** Set the sampler and infer the type. */
+ void set_sampler(ir_dereference *sampler);
+
+ /**
+ * Do a reverse-lookup to translate a string into an ir_texture_opcode.
+ */
+ static ir_texture_opcode get_opcode(const char *);
+
+ enum ir_texture_opcode op;
+
+ /** Sampler to use for the texture access. */
+ ir_dereference *sampler;
+
+ /** Texture coordinate to sample */
+ ir_rvalue *coordinate;
+
+ /**
+ * Value used for projective divide.
+ *
+ * If there is no projective divide (the common case), this will be
+ * \c NULL. Optimization passes should check for this to point to a constant
+ * of 1.0 and replace that with \c NULL.
+ */
+ ir_rvalue *projector;
+
+ /**
+ * Coordinate used for comparison on shadow look-ups.
+ *
+ * If there is no shadow comparison, this will be \c NULL. For the
+ * \c ir_txf opcode, this *must* be \c NULL.
+ */
+ ir_rvalue *shadow_comparitor;
+
+ /** Explicit texel offsets. */
+ signed char offsets[3];
+
+ union {
+ ir_rvalue *lod; /**< Floating point LOD */
+ ir_rvalue *bias; /**< Floating point LOD bias */
+ struct {
+ ir_rvalue *dPdx; /**< Partial derivative of coordinate wrt X */
+ ir_rvalue *dPdy; /**< Partial derivative of coordinate wrt Y */
+ } grad;
+ } lod_info;
+};
+
+
struct ir_swizzle_mask {
unsigned x:2;
unsigned y:2;
return this;
}
- virtual void accept(ir_visitor *v)
- {
- v->visit(this);
- }
-
bool is_lvalue();
/**
* Get the variable that is ultimately referenced by an r-value
*/
virtual ir_variable *variable_referenced() = 0;
-
- enum ir_deref_mode {
- ir_reference_variable,
- ir_reference_array,
- ir_reference_record
- } mode;
-
- /**
- * Object being dereferenced.
- *
- * Must be either an \c ir_variable or an \c ir_rvalue.
- */
- ir_instruction *var;
-
- union {
- ir_rvalue *array_index;
- const char *field;
- } selector;
-
-protected:
- ir_dereference(ir_deref_mode mode)
- : mode(mode)
- {
- /* empty */
- }
};
*/
virtual ir_variable *variable_referenced()
{
- return (ir_variable *) this->var;
+ return this->var;
+ }
+
+ virtual ir_variable *whole_variable_referenced()
+ {
+ /* ir_dereference_variable objects always dereference the entire
+ * variable. However, if this dereference is dereferenced by anything
+ * else, the complete deferefernce chain is not a whole-variable
+ * dereference. This method should only be called on the top most
+ * ir_rvalue in a dereference chain.
+ */
+ return this->var;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
}
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /**
+ * Object being dereferenced.
+ */
+ ir_variable *var;
};
ir_dereference_array(ir_variable *var, ir_rvalue *array_index);
+ virtual ir_dereference_array *as_dereference_array()
+ {
+ return this;
+ }
+
/**
* Get the variable that is ultimately referenced by an r-value
*/
virtual ir_variable *variable_referenced()
{
- return ((ir_rvalue *) this->var)->variable_referenced();
+ return this->array->variable_referenced();
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
}
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+ ir_rvalue *array;
+ ir_rvalue *array_index;
+
private:
void set_array(ir_rvalue *value);
};
*/
virtual ir_variable *variable_referenced()
{
- return ((ir_rvalue *) this->var)->variable_referenced();
+ return this->record->variable_referenced();
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
}
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ ir_rvalue *record;
+ const char *field;
+};
+
+
+/**
+ * Data stored in an ir_constant
+ */
+union ir_constant_data {
+ unsigned u[16];
+ int i[16];
+ float f[16];
+ bool b[16];
};
class ir_constant : public ir_rvalue {
public:
- ir_constant(const struct glsl_type *type, const void *data);
+ ir_constant(const struct glsl_type *type, const ir_constant_data *data);
ir_constant(bool b);
ir_constant(unsigned int u);
ir_constant(int i);
ir_constant(float f);
+ /**
+ * Construct an ir_constant from a list of ir_constant values
+ */
+ ir_constant(const struct glsl_type *type, exec_list *values);
+
+ /**
+ * Construct an ir_constant from a scalar component of another ir_constant
+ *
+ * The new \c ir_constant inherits the type of the component from the
+ * source constant.
+ *
+ * \note
+ * In the case of a matrix constant, the new constant is a scalar, \b not
+ * a vector.
+ */
+ ir_constant(const ir_constant *c, unsigned i);
+
virtual ir_constant *as_constant()
{
return this;
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- ir_constant *clone()
- {
- return new ir_constant(this->type, &this->value);
- }
+ ir_constant *clone();
+
+ /**
+ * Get a particular component of a constant as a specific type
+ *
+ * This is useful, for example, to get a value from an integer constant
+ * as a float or bool. This appears frequently when constructors are
+ * called with all constant parameters.
+ */
+ /*@{*/
+ bool get_bool_component(unsigned i) const;
+ float get_float_component(unsigned i) const;
+ int get_int_component(unsigned i) const;
+ unsigned get_uint_component(unsigned i) const;
+ /*@}*/
+
+ ir_constant *get_record_field(const char *name);
+
+ /**
+ * Determine whether a constant has the same value as another constant
+ */
+ bool has_value(const ir_constant *) const;
/**
* Value of the constant.
* by the type associated with the \c ir_instruction. Constants may be
* scalars, vectors, or matrices.
*/
- union {
- unsigned u[16];
- int i[16];
- float f[16];
- bool b[16];
- } value;
+ union ir_constant_data value;
+
+ exec_list components;
+
+private:
+ /**
+ * Parameterless constructor only used by the clone method
+ */
+ ir_constant(void);
};
void
visit_exec_list(exec_list *list, ir_visitor *visitor);
+void validate_ir_tree(exec_list *instructions);
+
extern void
_mesa_glsl_initialize_variables(exec_list *instructions,
struct _mesa_glsl_parse_state *state);