Fix 'make check' in src/mapi/glapi/tests when builddir != srcdir
[mesa.git] / src / glsl / ir.h
index 756ce9c7cd33b6857062d1eb48575971798e28c0..b898d619b3eaf9b61490f3db8f0b6e8d516e07df 100644 (file)
@@ -133,11 +133,22 @@ public:
    virtual class ir_return *            as_return()           { return NULL; }
    virtual class ir_if *                as_if()               { return NULL; }
    virtual class ir_swizzle *           as_swizzle()          { return NULL; }
+   virtual class ir_texture *           as_texture()          { return NULL; }
    virtual class ir_constant *          as_constant()         { return NULL; }
    virtual class ir_discard *           as_discard()          { return NULL; }
    virtual class ir_jump *              as_jump()             { return NULL; }
    /*@}*/
 
+   /**
+    * IR equality method: Return true if the referenced instruction would
+    * return the same value as this one.
+    *
+    * This intended to be used for CSE and algebraic optimizations, on rvalues
+    * in particular.  No support for other instruction types (assignments,
+    * jumps, calls, etc.) is planned.
+    */
+   virtual bool equals(ir_instruction *ir);
+
 protected:
    ir_instruction()
    {
@@ -282,6 +293,34 @@ enum ir_variable_mode {
    ir_var_mode_count   /**< Number of variable modes */
 };
 
+/**
+ * Enum keeping track of how a variable was declared.  For error checking of
+ * the gl_PerVertex redeclaration rules.
+ */
+enum ir_var_declaration_type {
+   /**
+    * Normal declaration (for most variables, this means an explicit
+    * declaration.  Exception: temporaries are always implicitly declared, but
+    * they still use ir_var_declared_normally).
+    *
+    * Note: an ir_variable that represents a named interface block uses
+    * ir_var_declared_normally.
+    */
+   ir_var_declared_normally = 0,
+
+   /**
+    * Variable was explicitly declared (or re-declared) in an unnamed
+    * interface block.
+    */
+   ir_var_declared_in_block,
+
+   /**
+    * Variable is an implicitly declared built-in that has not been explicitly
+    * re-declared by the shader.
+    */
+   ir_var_declared_implicitly,
+};
+
 /**
  * \brief Layout qualifiers for gl_FragDepth.
  *
@@ -312,6 +351,22 @@ struct ir_state_slot {
    int swizzle;
 };
 
+
+/**
+ * Get the string value for an interpolation qualifier
+ *
+ * \return The string that would be used in a shader to specify \c
+ * mode will be returned.
+ *
+ * This function is used to generate error messages of the form "shader
+ * uses %s interpolation qualifier", so in the case where there is no
+ * interpolation qualifier, it returns "no".
+ *
+ * This function should only be used on a shader input or output variable.
+ */
+const char *interpolation_string(unsigned interpolation);
+
+
 class ir_variable : public ir_instruction {
 public:
    ir_variable(const struct glsl_type *, const char *, ir_variable_mode);
@@ -331,20 +386,6 @@ public:
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
 
-   /**
-    * Get the string value for the interpolation qualifier
-    *
-    * \return The string that would be used in a shader to specify \c
-    * mode will be returned.
-    *
-    * This function is used to generate error messages of the form "shader
-    * uses %s interpolation qualifier", so in the case where there is no
-    * interpolation qualifier, it returns "no".
-    *
-    * This function should only be used on a shader input or output variable.
-    */
-   const char *interpolation_string() const;
-
    /**
     * Determine how this variable should be interpolated based on its
     * interpolation qualifier (if present), whether it is gl_Color or
@@ -391,6 +432,65 @@ public:
          || (t->is_array() && t->fields.array == this->interface_type);
     }
 
+   /**
+    * Set this->interface_type on a newly created variable.
+    */
+   void init_interface_type(const struct glsl_type *type)
+   {
+      assert(this->interface_type == NULL);
+      this->interface_type = type;
+      if (this->is_interface_instance()) {
+         this->max_ifc_array_access =
+            rzalloc_array(this, unsigned, type->length);
+      }
+   }
+
+   /**
+    * Change this->interface_type on a variable that previously had a
+    * different, but compatible, interface_type.  This is used during linking
+    * to set the size of arrays in interface blocks.
+    */
+   void change_interface_type(const struct glsl_type *type)
+   {
+      if (this->max_ifc_array_access != NULL) {
+         /* max_ifc_array_access has already been allocated, so make sure the
+          * new interface has the same number of fields as the old one.
+          */
+         assert(this->interface_type->length == type->length);
+      }
+      this->interface_type = type;
+   }
+
+   /**
+    * Change this->interface_type on a variable that previously had a
+    * different, and incompatible, interface_type. This is used during
+    * compilation to handle redeclaration of the built-in gl_PerVertex
+    * interface block.
+    */
+   void reinit_interface_type(const struct glsl_type *type)
+   {
+      if (this->max_ifc_array_access != NULL) {
+#ifndef _NDEBUG
+         /* Redeclaring gl_PerVertex is only allowed if none of the built-ins
+          * it defines have been accessed yet; so it's safe to throw away the
+          * old max_ifc_array_access pointer, since all of its values are
+          * zero.
+          */
+         for (unsigned i = 0; i < this->interface_type->length; i++)
+            assert(this->max_ifc_array_access[i] == 0);
+#endif
+         ralloc_free(this->max_ifc_array_access);
+         this->max_ifc_array_access = NULL;
+      }
+      this->interface_type = NULL;
+      init_interface_type(type);
+   }
+
+   const glsl_type *get_interface_type() const
+   {
+      return this->interface_type;
+   }
+
    /**
     * Declared type of the variable
     */
@@ -408,6 +508,19 @@ public:
     */
    unsigned max_array_access;
 
+   /**
+    * For variables which satisfy the is_interface_instance() predicate, this
+    * points to an array of integers such that if the ith member of the
+    * interface block is an array, max_ifc_array_access[i] is the maximum
+    * array element of that member that has been accessed.  If the ith member
+    * of the interface block is not an array, max_ifc_array_access[i] is
+    * unused.
+    *
+    * For variables whose type is not an interface block, this pointer is
+    * NULL.
+    */
+   unsigned *max_ifc_array_access;
+
    /**
     * Is the variable read-only?
     *
@@ -440,6 +553,14 @@ public:
     */
    unsigned assigned:1;
 
+   /**
+    * Enum indicating how the variable was declared.  See
+    * ir_var_declaration_type.
+    *
+    * This is used to detect certain kinds of illegal variable redeclarations.
+    */
+   unsigned how_declared:2;
+
    /**
     * Storage class of the variable.
     *
@@ -506,6 +627,24 @@ public:
     */
    unsigned location_frac:2;
 
+   /**
+    * Non-zero if this variable was created by lowering a named interface
+    * block which was not an array.
+    *
+    * Note that this variable and \c from_named_ifc_block_array will never
+    * both be non-zero.
+    */
+   unsigned from_named_ifc_block_nonarray:1;
+
+   /**
+    * Non-zero if this variable was created by lowering a named interface
+    * block which was an array.
+    *
+    * Note that this variable and \c from_named_ifc_block_nonarray will never
+    * both be non-zero.
+    */
+   unsigned from_named_ifc_block_array:1;
+
    /**
     * \brief Layout qualifier for gl_FragDepth.
     *
@@ -546,6 +685,14 @@ public:
     */
    int binding;
 
+   /**
+    * Location an atomic counter is stored at.
+    */
+   struct {
+      unsigned buffer_index;
+      unsigned offset;
+   } atomic;
+
    /**
     * Built-in state that backs this uniform
     *
@@ -582,6 +729,7 @@ public:
     */
    ir_constant *constant_initializer;
 
+private:
    /**
     * For variables that are in an interface block or are an instance of an
     * interface block, this is the \c GLSL_TYPE_INTERFACE type for that block.
@@ -686,6 +834,12 @@ public:
    /** Whether or not this function signature is a built-in. */
    bool is_builtin() const;
 
+   /**
+    * Whether or not this function is an intrinsic to be implemented
+    * by the driver.
+    */
+   bool is_intrinsic;
+
    /** Whether or not a built-in is available for this shader. */
    bool is_builtin_available(const _mesa_glsl_parse_state *state) const;
 
@@ -878,13 +1032,33 @@ public:
     * If \c from and \c to are the same value, the loop will execute once.
     */
    /*@{*/
-   ir_rvalue *from;             /** Value of the loop counter on the first
-                                * iteration of the loop.
-                                */
-   ir_rvalue *to;               /** Value of the loop counter on the last
-                                * iteration of the loop.
-                                */
+
+   /**
+    * Value which should be assigned to \c counter before the first iteration
+    * of the loop.  Must be non-null whenever \c counter is non-null, and vice
+    * versa.
+    */
+   ir_rvalue *from;
+
+   /**
+    * Value which \c counter should be compared to in order to determine
+    * whether to exit the loop.  Must be non-null whenever \c counter is
+    * non-null, and vice versa.
+    */
+   ir_rvalue *to;
+
+   /**
+    * Value which should be added to \c counter at the end of each loop
+    * iteration.  Must be non-null whenever \c counter is non-null, and vice
+    * versa.
+    */
    ir_rvalue *increment;
+
+   /**
+    * Variable which counts loop iterations.  This is a brand new ir_variable
+    * declaration (not a reference to a previously declared ir_variable, as in
+    * ir_dereference_variable).
+    */
    ir_variable *counter;
 
    /**
@@ -893,6 +1067,8 @@ public:
     * If any of the loop control fields are non-\c NULL, this field must be
     * one of \c ir_binop_less, \c ir_binop_greater, \c ir_binop_lequal,
     * \c ir_binop_gequal, \c ir_binop_equal, or \c ir_binop_nequal.
+    *
+    * Ignored if \c counter is NULL.
     */
    int cmp;
    /*@}*/
@@ -1091,7 +1267,8 @@ enum ir_expression_operation {
 
    ir_binop_add,
    ir_binop_sub,
-   ir_binop_mul,
+   ir_binop_mul,       /**< Floating-point or low 32-bit integer multiply. */
+   ir_binop_imul_high, /**< Calculates the high 32-bits of a 64-bit multiply. */
    ir_binop_div,
 
    /**
@@ -1296,6 +1473,8 @@ public:
       return this;
    }
 
+   virtual bool equals(ir_instruction *ir);
+
    virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
 
    /**
@@ -1623,8 +1802,15 @@ public:
       v->visit(this);
    }
 
+   virtual ir_texture *as_texture()
+   {
+      return this;
+   }
+
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual bool equals(ir_instruction *ir);
+
    /**
     * Return a string representing the ir_texture_opcode.
     */
@@ -1729,6 +1915,8 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual bool equals(ir_instruction *ir);
+
    bool is_lvalue() const
    {
       return val->is_lvalue() && !mask.has_duplicates;
@@ -1793,6 +1981,8 @@ public:
       return this;
    }
 
+   virtual bool equals(ir_instruction *ir);
+
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
@@ -1851,6 +2041,8 @@ public:
       return this;
    }
 
+   virtual bool equals(ir_instruction *ir);
+
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
@@ -1985,6 +2177,8 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual bool equals(ir_instruction *ir);
+
    /**
     * Get a particular component of a constant as a specific type
     *
@@ -2198,6 +2392,9 @@ extern char *
 prototype_string(const glsl_type *return_type, const char *name,
                 exec_list *parameters);
 
+const char *
+mode_string(const ir_variable *var);
+
 extern "C" {
 #endif /* __cplusplus */