ir_variable: Add method to get string representing interpolation qualifier
[mesa.git] / ir.h
diff --git a/ir.h b/ir.h
index f785ddb63736ed3e032af760c91ac593df5740bd..04ecb582e482268f3f18a85ab1210b5974e4f707 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -26,6 +26,9 @@
 #ifndef IR_H
 #define IR_H
 
+#include <cstdio>
+#include <cstdlib>
+
 #include "list.h"
 #include "ir_visitor.h"
 #include "ir_hierarchical_visitor.h"
@@ -42,6 +45,10 @@ public:
    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;
 
@@ -56,8 +63,8 @@ public:
    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; }
@@ -95,6 +102,21 @@ public:
       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()
    {
@@ -155,6 +177,16 @@ public:
       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;
 
    /**
@@ -479,6 +511,14 @@ enum ir_expression_operation {
    ir_unop_cos,
    /*@}*/
 
+   /**
+    * \name Partial derivatives.
+    */
+   /*@{*/
+   ir_unop_dFdx,
+   ir_unop_dFdy,
+   /*@}*/
+
    ir_binop_add,
    ir_binop_sub,
    ir_binop_mul,
@@ -670,7 +710,6 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-private:
    ir_rvalue *value;
 };
 
@@ -723,6 +762,103 @@ private:
 /*@}*/
 
 
+/**
+ * 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;
@@ -793,42 +929,12 @@ public:
       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 */
-   }
 };
 
 
@@ -841,10 +947,31 @@ public:
     */
    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;
 };
 
 
@@ -854,16 +981,29 @@ public:
 
    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);
 };
@@ -880,21 +1020,57 @@ public:
     */
    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;
@@ -907,10 +1083,28 @@ public:
 
    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.
@@ -919,17 +1113,22 @@ public:
     * 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);