Add vulkan driver for BDW
[mesa.git] / src / glsl / ir.h
index 4cb1202e65bf93c0cebff1862c266c115c2568cc..fdb595106c2bb7c6ea05583a2646d0af795700b2 100644 (file)
@@ -29,7 +29,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "ralloc.h"
+#include "util/ralloc.h"
 #include "glsl_types.h"
 #include "list.h"
 #include "ir_visitor.h"
  * types, this allows writing very straightforward, readable code.
  */
 enum ir_node_type {
-   /**
-    * Zero is unused so that the IR validator can detect cases where
-    * \c ir_instruction::ir_type has not been initialized.
-    */
-   ir_type_unset,
-   ir_type_variable,
-   ir_type_assignment,
-   ir_type_call,
-   ir_type_constant,
    ir_type_dereference_array,
    ir_type_dereference_record,
    ir_type_dereference_variable,
-   ir_type_discard,
+   ir_type_constant,
    ir_type_expression,
+   ir_type_swizzle,
+   ir_type_texture,
+   ir_type_variable,
+   ir_type_assignment,
+   ir_type_call,
    ir_type_function,
    ir_type_function_signature,
    ir_type_if,
    ir_type_loop,
    ir_type_loop_jump,
    ir_type_return,
-   ir_type_swizzle,
-   ir_type_texture,
+   ir_type_discard,
    ir_type_emit_vertex,
    ir_type_end_primitive,
-   ir_type_max /**< maximum ir_type enum number, for validation */
+   ir_type_max, /**< maximum ir_type enum number, for validation */
+   ir_type_unset = ir_type_max
 };
 
+
 /**
  * Base class of all IR instructions
  */
@@ -105,12 +102,38 @@ public:
 
    /** ir_print_visitor helper for debugging. */
    void print(void) const;
+   void fprint(FILE *f) const;
 
    virtual void accept(ir_visitor *) = 0;
    virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0;
    virtual ir_instruction *clone(void *mem_ctx,
                                 struct hash_table *ht) const = 0;
 
+   bool is_rvalue() const
+   {
+      return ir_type == ir_type_dereference_array ||
+             ir_type == ir_type_dereference_record ||
+             ir_type == ir_type_dereference_variable ||
+             ir_type == ir_type_constant ||
+             ir_type == ir_type_expression ||
+             ir_type == ir_type_swizzle ||
+             ir_type == ir_type_texture;
+   }
+
+   bool is_dereference() const
+   {
+      return ir_type == ir_type_dereference_array ||
+             ir_type == ir_type_dereference_record ||
+             ir_type == ir_type_dereference_variable;
+   }
+
+   bool is_jump() const
+   {
+      return ir_type == ir_type_loop_jump ||
+             ir_type == ir_type_return ||
+             ir_type == ir_type_discard;
+   }
+
    /**
     * \name IR instruction downcast functions
     *
@@ -119,29 +142,73 @@ public:
     * Additional downcast functions will be added as needed.
     */
    /*@{*/
-   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_dereference_variable *as_dereference_variable() { return NULL; }
-   virtual class ir_dereference_record *as_dereference_record() { return NULL; }
-   virtual class ir_expression *        as_expression()       { return NULL; }
-   virtual class ir_rvalue *            as_rvalue()           { 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; }
-   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_constant *          as_constant()         { return NULL; }
-   virtual class ir_discard *           as_discard()          { return NULL; }
-   virtual class ir_jump *              as_jump()             { return NULL; }
+   #define AS_BASE(TYPE)                                \
+   class ir_##TYPE *as_##TYPE()                         \
+   {                                                    \
+      assume(this != NULL);                             \
+      return is_##TYPE() ? (ir_##TYPE *) this : NULL;   \
+   }                                                    \
+   const class ir_##TYPE *as_##TYPE() const             \
+   {                                                    \
+      assume(this != NULL);                             \
+      return is_##TYPE() ? (ir_##TYPE *) this : NULL;   \
+   }
+
+   AS_BASE(rvalue)
+   AS_BASE(dereference)
+   AS_BASE(jump)
+   #undef AS_BASE
+
+   #define AS_CHILD(TYPE) \
+   class ir_##TYPE * as_##TYPE() \
+   { \
+      assume(this != NULL);                                         \
+      return ir_type == ir_type_##TYPE ? (ir_##TYPE *) this : NULL; \
+   }                                                                      \
+   const class ir_##TYPE * as_##TYPE() const                              \
+   {                                                                      \
+      assume(this != NULL);                                               \
+      return ir_type == ir_type_##TYPE ? (const ir_##TYPE *) this : NULL; \
+   }
+   AS_CHILD(variable)
+   AS_CHILD(function)
+   AS_CHILD(dereference_array)
+   AS_CHILD(dereference_variable)
+   AS_CHILD(dereference_record)
+   AS_CHILD(expression)
+   AS_CHILD(loop)
+   AS_CHILD(assignment)
+   AS_CHILD(call)
+   AS_CHILD(return)
+   AS_CHILD(if)
+   AS_CHILD(swizzle)
+   AS_CHILD(texture)
+   AS_CHILD(constant)
+   AS_CHILD(discard)
+   #undef AS_CHILD
    /*@}*/
 
+   /**
+    * 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(const ir_instruction *ir,
+                       enum ir_node_type ignore = ir_type_unset) const;
+
 protected:
+   ir_instruction(enum ir_node_type t)
+      : ir_type(t)
+   {
+   }
+
+private:
    ir_instruction()
    {
-      ir_type = ir_type_unset;
+      assert(!"Should not get here.");
    }
 };
 
@@ -164,11 +231,6 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_rvalue * as_rvalue()
-   {
-      return this;
-   }
-
    ir_rvalue *as_rvalue_to_saturate();
 
    virtual bool is_lvalue() const
@@ -207,8 +269,7 @@ public:
     * 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,
-    *     ir_constant::is_basis
+    * \sa ir_constant::has_value, ir_rvalue::is_one, ir_rvalue::is_negative_one
     */
    virtual bool is_zero() const;
 
@@ -220,8 +281,7 @@ public:
     * 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,
-    *     ir_constant::is_basis
+    * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_negative_one
     */
    virtual bool is_one() const;
 
@@ -234,24 +294,16 @@ public:
     * 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
+    * Determine if an r-value is an unsigned integer constant which can be
+    * stored in 16 bits.
     *
-    * 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
+    * \sa ir_constant::is_uint16_constant.
     */
-   virtual bool is_basis() const;
-
+   virtual bool is_uint16_constant() const { return false; }
 
    /**
     * Return a generic value of error_type.
@@ -261,7 +313,7 @@ public:
    static ir_rvalue *error_value(void *mem_ctx);
 
 protected:
-   ir_rvalue();
+   ir_rvalue(enum ir_node_type t);
 };
 
 
@@ -282,6 +334,40 @@ 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,
+
+   /**
+    * Variable is implicitly generated by the compiler and should not be
+    * visible via the API.
+    */
+   ir_var_hidden,
+};
+
 /**
  * \brief Layout qualifiers for gl_FragDepth.
  *
@@ -312,17 +398,28 @@ 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);
 
    virtual ir_variable *clone(void *mem_ctx, struct hash_table *ht) const;
 
-   virtual ir_variable *as_variable()
-   {
-      return this;
-   }
-
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -331,20 +428,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
@@ -361,7 +444,7 @@ public:
     */
    inline bool is_in_uniform_block() const
    {
-      return this->mode == ir_var_uniform && this->interface_type != NULL;
+      return this->data.mode == ir_var_uniform && this->interface_type != NULL;
    }
 
    /**
@@ -385,187 +468,394 @@ public:
     */
    inline bool is_interface_instance() const
    {
-      const glsl_type *const t = this->type;
-
-      return (t == this->interface_type)
-         || (t->is_array() && t->fields.array == this->interface_type);
-    }
+      return this->type->without_array() == this->interface_type;
+   }
 
    /**
-    * Declared type of the variable
+    * Set this->interface_type on a newly created variable.
     */
-   const struct glsl_type *type;
+   void init_interface_type(const struct glsl_type *type)
+   {
+      assert(this->interface_type == NULL);
+      this->interface_type = type;
+      if (this->is_interface_instance()) {
+         this->u.max_ifc_array_access =
+            rzalloc_array(this, unsigned, type->length);
+      }
+   }
 
    /**
-    * Declared name of the variable
+    * 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.
     */
-   const char *name;
+   void change_interface_type(const struct glsl_type *type)
+   {
+      if (this->u.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;
+   }
 
    /**
-    * Highest element accessed with a constant expression array index
-    *
-    * Not used for non-array variables.
+    * 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.
     */
-   unsigned max_array_access;
+   void reinit_interface_type(const struct glsl_type *type)
+   {
+      if (this->u.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->u.max_ifc_array_access[i] == 0);
+#endif
+         ralloc_free(this->u.max_ifc_array_access);
+         this->u.max_ifc_array_access = NULL;
+      }
+      this->interface_type = NULL;
+      init_interface_type(type);
+   }
 
-   /**
-    * Is the variable read-only?
-    *
-    * This is set for variables declared as \c const, shader inputs,
-    * and uniforms.
-    */
-   unsigned read_only:1;
-   unsigned centroid:1;
-   unsigned invariant:1;
+   const glsl_type *get_interface_type() const
+   {
+      return this->interface_type;
+   }
 
    /**
-    * Has this variable been used for reading or writing?
-    *
-    * 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.
+    * Get the max_ifc_array_access pointer
     *
-    * This is only maintained in the ast_to_hir.cpp path, not in
-    * Mesa's fixed function or ARB program paths.
+    * A "set" function is not needed because the array is dynmically allocated
+    * as necessary.
     */
-   unsigned used:1;
+   inline unsigned *get_max_ifc_array_access()
+   {
+      assert(this->data._num_state_slots == 0);
+      return this->u.max_ifc_array_access;
+   }
 
-   /**
-    * 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;
+   inline unsigned get_num_state_slots() const
+   {
+      assert(!this->is_interface_instance()
+             || this->data._num_state_slots == 0);
+      return this->data._num_state_slots;
+   }
 
-   /**
-    * Storage class of the variable.
-    *
-    * \sa ir_variable_mode
-    */
-   unsigned mode:4;
+   inline void set_num_state_slots(unsigned n)
+   {
+      assert(!this->is_interface_instance()
+             || n == 0);
+      this->data._num_state_slots = n;
+   }
 
-   /**
-    * Interpolation mode for shader inputs / outputs
-    *
-    * \sa ir_variable_interpolation
-    */
-   unsigned interpolation:2;
+   inline ir_state_slot *get_state_slots()
+   {
+      return this->is_interface_instance() ? NULL : this->u.state_slots;
+   }
 
-   /**
-    * \name ARB_fragment_coord_conventions
-    * @{
-    */
-   unsigned origin_upper_left:1;
-   unsigned pixel_center_integer:1;
-   /*@}*/
+   inline const ir_state_slot *get_state_slots() const
+   {
+      return this->is_interface_instance() ? NULL : this->u.state_slots;
+   }
 
-   /**
-    * Was the location explicitly set in the shader?
-    *
-    * If the location is explicitly set in the shader, it \b cannot be changed
-    * by the linker or by the API (e.g., calls to \c glBindAttribLocation have
-    * no effect).
-    */
-   unsigned explicit_location:1;
-   unsigned explicit_index:1;
+   inline ir_state_slot *allocate_state_slots(unsigned n)
+   {
+      assert(!this->is_interface_instance());
 
-   /**
-    * Was an initial binding explicitly set in the shader?
-    *
-    * If so, constant_value contains an integer ir_constant representing the
-    * initial binding point.
-    */
-   unsigned explicit_binding:1;
+      this->u.state_slots = ralloc_array(this, ir_state_slot, n);
+      this->data._num_state_slots = 0;
 
-   /**
-    * Does this variable have an initializer?
-    *
-    * This is used by the linker to cross-validiate initializers of global
-    * variables.
-    */
-   unsigned has_initializer:1;
+      if (this->u.state_slots != NULL)
+         this->data._num_state_slots = n;
 
-   /**
-    * Is this variable a generic output or input that has not yet been matched
-    * up to a variable in another stage of the pipeline?
-    *
-    * This is used by the linker as scratch storage while assigning locations
-    * to generic inputs and outputs.
-    */
-   unsigned is_unmatched_generic_inout:1;
+      return this->u.state_slots;
+   }
 
-   /**
-    * If non-zero, then this variable may be packed along with other variables
-    * into a single varying slot, so this offset should be applied when
-    * accessing components.  For example, an offset of 1 means that the x
-    * component of this variable is actually stored in component y of the
-    * location specified by \c location.
-    */
-   unsigned location_frac:2;
+   inline bool is_name_ralloced() const
+   {
+      return this->name != ir_variable::tmp_name;
+   }
 
    /**
-    * \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.
+    * Enable emitting extension warnings for this variable
     */
-   ir_depth_layout depth_layout;
+   void enable_extension_warning(const char *extension);
 
    /**
-    * Storage location of the base of this variable
-    *
-    * The precise meaning of this field depends on the nature of the variable.
-    *
-    *   - Vertex shader input: one of the values from \c gl_vert_attrib.
-    *   - Vertex shader output: one of the values from \c gl_varying_slot.
-    *   - Geometry shader input: one of the values from \c gl_varying_slot.
-    *   - Geometry shader output: one of the values from \c gl_varying_slot.
-    *   - Fragment shader input: one of the values from \c gl_varying_slot.
-    *   - Fragment shader output: one of the values from \c gl_frag_result.
-    *   - 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.
+    * Get the extension warning string for this variable
     *
-    * If the variable is a uniform, shader input, or shader output, and the
-    * slot has not been assigned, the value will be -1.
+    * If warnings are not enabled, \c NULL is returned.
     */
-   int location;
+   const char *get_extension_warning() const;
 
    /**
-    * output index for dual source blending.
+    * Declared type of the variable
     */
-   int index;
+   const struct glsl_type *type;
 
    /**
-    * Initial binding point for a sampler or UBO.
-    *
-    * For array types, this represents the binding point for the first element.
+    * Declared name of the variable
     */
-   int binding;
+   const char *name;
 
-   /**
-    * Built-in state that backs this uniform
-    *
-    * Once set at variable creation, \c state_slots must remain invariant.
-    * This is because, ideally, this array would be shared by all clones of
-    * this variable in the IR tree.  In other words, we'd really like for it
-    * to be a fly-weight.
-    *
-    * If the variable is not a uniform, \c num_state_slots will be zero and
-    * \c state_slots will be \c NULL.
-    */
-   /*@{*/
-   unsigned num_state_slots;    /**< Number of state slots used */
-   ir_state_slot *state_slots;  /**< State descriptors. */
-   /*@}*/
+   struct ir_variable_data {
 
-   /**
-    * Emit a warning if this variable is accessed.
-    */
-   const char *warn_extension;
+      /**
+       * Is the variable read-only?
+       *
+       * This is set for variables declared as \c const, shader inputs,
+       * and uniforms.
+       */
+      unsigned read_only:1;
+      unsigned centroid:1;
+      unsigned sample:1;
+      unsigned invariant:1;
+      unsigned precise:1;
+
+      /**
+       * Has this variable been used for reading or writing?
+       *
+       * 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;
+
+      /**
+       * 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.
+       *
+       * \sa ir_variable_mode
+       */
+      unsigned mode:4;
+
+      /**
+       * Interpolation mode for shader inputs / outputs
+       *
+       * \sa ir_variable_interpolation
+       */
+      unsigned interpolation:2;
+
+      /**
+       * \name ARB_fragment_coord_conventions
+       * @{
+       */
+      unsigned origin_upper_left:1;
+      unsigned pixel_center_integer:1;
+      /*@}*/
+
+      /**
+       * Was the location explicitly set in the shader?
+       *
+       * If the location is explicitly set in the shader, it \b cannot be changed
+       * by the linker or by the API (e.g., calls to \c glBindAttribLocation have
+       * no effect).
+       */
+      unsigned explicit_location:1;
+      unsigned explicit_index:1;
+
+      /**
+       * Do we have a Vulkan (group, index) qualifier for this variable?
+       */
+      unsigned vk_set:1;
+
+      /**
+       * Was an initial binding explicitly set in the shader?
+       *
+       * If so, constant_value contains an integer ir_constant representing the
+       * initial binding point.
+       */
+      unsigned explicit_binding:1;
+
+      /**
+       * Does this variable have an initializer?
+       *
+       * This is used by the linker to cross-validiate initializers of global
+       * variables.
+       */
+      unsigned has_initializer:1;
+
+      /**
+       * Is this variable a generic output or input that has not yet been matched
+       * up to a variable in another stage of the pipeline?
+       *
+       * This is used by the linker as scratch storage while assigning locations
+       * to generic inputs and outputs.
+       */
+      unsigned is_unmatched_generic_inout:1;
+
+      /**
+       * If non-zero, then this variable may be packed along with other variables
+       * into a single varying slot, so this offset should be applied when
+       * accessing components.  For example, an offset of 1 means that the x
+       * component of this variable is actually stored in component y of the
+       * location specified by \c location.
+       */
+      unsigned location_frac:2;
+
+      /**
+       * Layout of the matrix.  Uses glsl_matrix_layout values.
+       */
+      unsigned matrix_layout: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;
+
+      /**
+       * Non-zero if the variable must be a shader input. This is useful for
+       * constraints on function parameters.
+       */
+      unsigned must_be_shader_input:1;
+
+      /**
+       * Output index for dual source blending.
+       *
+       * \note
+       * The GLSL spec only allows the values 0 or 1 for the index in \b dual
+       * source blending.
+       *
+       * This is now also used for the Vulkan descriptor set index.
+       */
+      int16_t index;
+
+      /**
+       * \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:3;
+
+      /**
+       * ARB_shader_image_load_store qualifiers.
+       */
+      unsigned image_read_only:1; /**< "readonly" qualifier. */
+      unsigned image_write_only:1; /**< "writeonly" qualifier. */
+      unsigned image_coherent:1;
+      unsigned image_volatile:1;
+      unsigned image_restrict:1;
+
+      /**
+       * Emit a warning if this variable is accessed.
+       */
+   private:
+      uint8_t warn_extension_index;
+
+   public:
+      /** Image internal format if specified explicitly, otherwise GL_NONE. */
+      uint16_t image_format;
+
+   private:
+      /**
+       * Number of state slots used
+       *
+       * \note
+       * This could be stored in as few as 7-bits, if necessary.  If it is made
+       * smaller, add an assertion to \c ir_variable::allocate_state_slots to
+       * be safe.
+       */
+      uint16_t _num_state_slots;
+
+   public:
+      /**
+       * Initial binding point for a sampler, atomic, or UBO.
+       *
+       * For array types, this represents the binding point for the first element.
+       */
+      int16_t binding;
+
+      /**
+       * Vulkan descriptor set for the resource.
+       */
+      int16_t set;
+
+      /**
+       * Storage location of the base of this variable
+       *
+       * The precise meaning of this field depends on the nature of the variable.
+       *
+       *   - Vertex shader input: one of the values from \c gl_vert_attrib.
+       *   - Vertex shader output: one of the values from \c gl_varying_slot.
+       *   - Geometry shader input: one of the values from \c gl_varying_slot.
+       *   - Geometry shader output: one of the values from \c gl_varying_slot.
+       *   - Fragment shader input: one of the values from \c gl_varying_slot.
+       *   - Fragment shader output: one of the values from \c gl_frag_result.
+       *   - 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
+       * slot has not been assigned, the value will be -1.
+       */
+      int location;
+
+      /**
+       * Vertex stream output identifier.
+       */
+      unsigned stream;
+
+      /**
+       * Location an atomic counter is stored at.
+       */
+      struct {
+         unsigned offset;
+      } atomic;
+
+      /**
+       * Highest element accessed with a constant expression array index
+       *
+       * Not used for non-array variables.
+       */
+      unsigned max_array_access;
+
+      /**
+       * Allow (only) ir_variable direct access private members.
+       */
+      friend class ir_variable;
+   } data;
 
    /**
     * Value assigned in the initializer of a variable declared "const"
@@ -582,6 +872,34 @@ public:
     */
    ir_constant *constant_initializer;
 
+private:
+   static const char *const warn_extension_table[];
+
+   union {
+      /**
+       * 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;
+
+      /**
+       * Built-in state that backs this uniform
+       *
+       * Once set at variable creation, \c state_slots must remain invariant.
+       *
+       * If the variable is not a uniform, \c _num_state_slots will be zero
+       * and \c state_slots will be \c NULL.
+       */
+      ir_state_slot *state_slots;
+   } u;
+
    /**
     * 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.
@@ -589,8 +907,37 @@ public:
     * \sa ir_variable::location
     */
    const glsl_type *interface_type;
+
+   /**
+    * Name used for anonymous compiler temporaries
+    */
+   static const char tmp_name[];
+
+public:
+   /**
+    * Should the construct keep names for ir_var_temporary variables?
+    *
+    * When this global is false, names passed to the constructor for
+    * \c ir_var_temporary variables will be dropped.  Instead, the variable will
+    * be named "compiler_temp".  This name will be in static storage.
+    *
+    * \warning
+    * \b NEVER change the mode of an \c ir_var_temporary.
+    *
+    * \warning
+    * This variable is \b not thread-safe.  It is global, \b not
+    * per-context. It begins life false.  A context can, at some point, make
+    * it true.  From that point on, it will be true forever.  This should be
+    * okay since it will only be set true while debugging.
+    */
+   static bool temporaries_allocate_names;
 };
 
+/**
+ * A function that returns whether a built-in function is available in the
+ * current shading language (based on version, ES or desktop, and extensions).
+ */
+typedef bool (*builtin_available_predicate)(const _mesa_glsl_parse_state *);
 
 /*@{*/
 /**
@@ -602,7 +949,8 @@ class ir_function_signature : public ir_instruction {
     * an ir_function.
     */
 public:
-   ir_function_signature(const glsl_type *return_type);
+   ir_function_signature(const glsl_type *return_type,
+                         builtin_available_predicate builtin_avail = NULL);
 
    virtual ir_function_signature *clone(void *mem_ctx,
                                        struct hash_table *ht) const;
@@ -678,12 +1026,27 @@ public:
    unsigned is_defined:1;
 
    /** Whether or not this function signature is a built-in. */
-   unsigned is_builtin:1;
+   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;
 
    /** Body of instructions in the function. */
    struct exec_list body;
 
 private:
+   /**
+    * A function pointer to a predicate that answers whether a built-in
+    * function is available in the current shader.  NULL if not a built-in.
+    */
+   builtin_available_predicate builtin_avail;
+
    /** Function of which this signature is one overload. */
    class ir_function *_function;
 
@@ -720,11 +1083,6 @@ public:
 
    virtual ir_function *clone(void *mem_ctx, struct hash_table *ht) const;
 
-   virtual ir_function *as_function()
-   {
-      return this;
-   }
-
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -738,32 +1096,29 @@ public:
       this->signatures.push_tail(sig);
    }
 
-   /**
-    * Get an iterator for the set of function signatures
-    */
-   exec_list_iterator iterator()
-   {
-      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,
+   ir_function_signature *matching_signature(_mesa_glsl_parse_state *state,
+                                             const exec_list *actual_param,
+                                             bool allow_builtins,
                                             bool *match_is_exact);
 
    /**
     * Find a signature that matches a set of actual parameters, taking implicit
     * conversions into account.
     */
-   ir_function_signature *matching_signature(const exec_list *actual_param);
+   ir_function_signature *matching_signature(_mesa_glsl_parse_state *state,
+                                             const exec_list *actual_param,
+                                             bool allow_builtins);
 
    /**
     * Find a signature that exactly matches a set of actual parameters without
     * any implicit type conversions.
     */
-   ir_function_signature *exact_matching_signature(const exec_list *actual_ps);
+   ir_function_signature *exact_matching_signature(_mesa_glsl_parse_state *state,
+                                                   const exec_list *actual_ps);
 
    /**
     * Name of the function.
@@ -792,18 +1147,12 @@ inline const char *ir_function_signature::function_name() const
 class ir_if : public ir_instruction {
 public:
    ir_if(ir_rvalue *condition)
-      : condition(condition)
+      : ir_instruction(ir_type_if), condition(condition)
    {
-      ir_type = ir_type_if;
    }
 
    virtual ir_if *clone(void *mem_ctx, struct hash_table *ht) const;
 
-   virtual ir_if *as_if()
-   {
-      return this;
-   }
-
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -835,49 +1184,8 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-   virtual ir_loop *as_loop()
-   {
-      return this;
-   }
-
-   /**
-    * Get an iterator for the instructions of the loop body
-    */
-   exec_list_iterator iterator()
-   {
-      return body_instructions.iterator();
-   }
-
    /** List of ir_instruction that make up the body of the loop. */
    exec_list body_instructions;
-
-   /**
-    * \name Loop counter and controls
-    *
-    * Represents a loop like a FORTRAN \c do-loop.
-    *
-    * \note
-    * 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.
-                                */
-   ir_rvalue *increment;
-   ir_variable *counter;
-
-   /**
-    * Comparison operation in the loop terminator.
-    *
-    * 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.
-    */
-   int cmp;
-   /*@}*/
 };
 
 
@@ -906,11 +1214,6 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-   virtual ir_assignment * as_assignment()
-   {
-      return this;
-   }
-
    /**
     * Get a whole variable written by an assignment
     *
@@ -993,6 +1296,13 @@ enum ir_expression_operation {
    ir_unop_u2f,         /**< Unsigned-to-float conversion. */
    ir_unop_i2u,         /**< Integer-to-unsigned conversion. */
    ir_unop_u2i,         /**< Unsigned-to-integer conversion. */
+   ir_unop_d2f,         /**< Double-to-float conversion. */
+   ir_unop_f2d,         /**< Float-to-double conversion. */
+   ir_unop_d2i,         /**< Double-to-integer conversion. */
+   ir_unop_i2d,         /**< Integer-to-double conversion. */
+   ir_unop_d2u,         /**< Double-to-unsigned conversion. */
+   ir_unop_u2d,         /**< Unsigned-to-double conversion. */
+   ir_unop_d2b,         /**< Double-to-boolean 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" */
@@ -1016,8 +1326,6 @@ enum ir_expression_operation {
    /*@{*/
    ir_unop_sin,
    ir_unop_cos,
-   ir_unop_sin_reduced,    /**< Reduced range sin. [-pi, pi] */
-   ir_unop_cos_reduced,    /**< Reduced range cos. [-pi, pi] */
    /*@}*/
 
    /**
@@ -1025,7 +1333,11 @@ enum ir_expression_operation {
     */
    /*@{*/
    ir_unop_dFdx,
+   ir_unop_dFdx_coarse,
+   ir_unop_dFdx_fine,
    ir_unop_dFdy,
+   ir_unop_dFdy_coarse,
+   ir_unop_dFdy_fine,
    /*@}*/
 
    /**
@@ -1064,18 +1376,54 @@ enum ir_expression_operation {
    ir_unop_find_lsb,
    /*@}*/
 
+   ir_unop_saturate,
+
+   /**
+    * \name Double packing, part of ARB_gpu_shader_fp64.
+    */
+   /*@{*/
+   ir_unop_pack_double_2x32,
+   ir_unop_unpack_double_2x32,
+   /*@}*/
+
+   ir_unop_frexp_sig,
+   ir_unop_frexp_exp,
+
    ir_unop_noise,
 
+   /**
+    * Interpolate fs input at centroid
+    *
+    * operand0 is the fs input.
+    */
+   ir_unop_interpolate_at_centroid,
+
    /**
     * A sentinel marking the last of the unary operations.
     */
-   ir_last_unop = ir_unop_noise,
+   ir_last_unop = ir_unop_interpolate_at_centroid,
 
    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,
 
+   /**
+    * Returns the carry resulting from the addition of the two arguments.
+    */
+   /*@{*/
+   ir_binop_carry,
+   /*@}*/
+
+   /**
+    * Returns the borrow resulting from the subtraction of the second argument
+    * from the first argument.
+    */
+   /*@{*/
+   ir_binop_borrow,
+   /*@}*/
+
    /**
     * Takes one of two combinations of arguments:
     *
@@ -1156,6 +1504,13 @@ enum ir_expression_operation {
     */
    ir_binop_ubo_load,
 
+   /**
+    * \name Multiplies a number by two to a power, part of ARB_gpu_shader5.
+    */
+   /*@{*/
+   ir_binop_ldexp,
+   /*@}*/
+
    /**
     * Extract a scalar from a vector
     *
@@ -1164,13 +1519,48 @@ enum ir_expression_operation {
     */
    ir_binop_vector_extract,
 
+   /**
+    * Interpolate fs input at offset
+    *
+    * operand0 is the fs input
+    * operand1 is the offset from the pixel center
+    */
+   ir_binop_interpolate_at_offset,
+
+   /**
+    * Interpolate fs input at sample position
+    *
+    * operand0 is the fs input
+    * operand1 is the sample ID
+    */
+   ir_binop_interpolate_at_sample,
+
    /**
     * A sentinel marking the last of the binary operations.
     */
-   ir_last_binop = ir_binop_vector_extract,
+   ir_last_binop = ir_binop_interpolate_at_sample,
+
+   /**
+    * \name Fused floating-point multiply-add, part of ARB_gpu_shader5.
+    */
+   /*@{*/
+   ir_triop_fma,
+   /*@}*/
 
    ir_triop_lrp,
 
+   /**
+    * \name Conditional Select
+    *
+    * A vector conditional select instruction (like ?:, but operating per-
+    * component on vectors).
+    *
+    * \see lower_instructions_visitor::ldexp_to_arith
+    */
+   /*@{*/
+   ir_triop_csel,
+   /*@}*/
+
    /**
     * \name Second half of a lowered bitfieldInsert() operation.
     *
@@ -1227,10 +1617,13 @@ public:
     */
    ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1);
 
-   virtual ir_expression *as_expression()
-   {
-      return this;
-   }
+   /**
+    * Constructor for ternary operation expressions
+    */
+   ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1, ir_rvalue *op2);
+
+   virtual bool equals(const ir_instruction *ir,
+                       enum ir_node_type ignore = ir_type_unset) const;
 
    virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
 
@@ -1260,6 +1653,18 @@ public:
         ? this->type->vector_elements : get_num_operands(operation);
    }
 
+   /**
+    * Return whether the expression operates on vectors horizontally.
+    */
+   bool is_horizontal() const
+   {
+      return operation == ir_binop_all_equal ||
+             operation == ir_binop_any_nequal ||
+             operation == ir_unop_any ||
+             operation == ir_binop_dot ||
+             operation == ir_quadop_vector;
+   }
+
    /**
     * Return a string representing this expression's operator.
     */
@@ -1297,23 +1702,17 @@ public:
    ir_call(ir_function_signature *callee,
           ir_dereference_variable *return_deref,
           exec_list *actual_parameters)
-      : return_deref(return_deref), callee(callee)
+      : ir_instruction(ir_type_call), return_deref(return_deref), callee(callee)
    {
-      ir_type = ir_type_call;
       assert(callee->return_type != NULL);
       actual_parameters->move_nodes_to(& this->actual_parameters);
-      this->use_builtin = callee->is_builtin;
+      this->use_builtin = callee->is_builtin();
    }
 
    virtual ir_call *clone(void *mem_ctx, struct hash_table *ht) const;
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_call *as_call()
-   {
-      return this;
-   }
-
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -1321,14 +1720,6 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-   /**
-    * Get an iterator for the set of acutal parameters
-    */
-   exec_list_iterator iterator()
-   {
-      return actual_parameters.iterator();
-   }
-
    /**
     * Get the name of the function being called.
     */
@@ -1370,39 +1761,26 @@ public:
 /*@{*/
 class ir_jump : public ir_instruction {
 protected:
-   ir_jump()
+   ir_jump(enum ir_node_type t)
+      : ir_instruction(t)
    {
-      ir_type = ir_type_unset;
-   }
-
-public:
-   virtual ir_jump *as_jump()
-   {
-      return this;
    }
 };
 
 class ir_return : public ir_jump {
 public:
    ir_return()
-      : value(NULL)
+      : ir_jump(ir_type_return), value(NULL)
    {
-      this->ir_type = ir_type_return;
    }
 
    ir_return(ir_rvalue *value)
-      : value(value)
+      : ir_jump(ir_type_return), value(value)
    {
-      this->ir_type = ir_type_return;
    }
 
    virtual ir_return *clone(void *mem_ctx, struct hash_table *) const;
 
-   virtual ir_return *as_return()
-   {
-      return this;
-   }
-
    ir_rvalue *get_value() const
    {
       return value;
@@ -1435,8 +1813,8 @@ public:
    };
 
    ir_loop_jump(jump_mode mode)
+      : ir_jump(ir_type_loop_jump)
    {
-      this->ir_type = ir_type_loop_jump;
       this->mode = mode;
    }
 
@@ -1469,14 +1847,14 @@ public:
 class ir_discard : public ir_jump {
 public:
    ir_discard()
+      : ir_jump(ir_type_discard)
    {
-      this->ir_type = ir_type_discard;
       this->condition = NULL;
    }
 
    ir_discard(ir_rvalue *cond)
+      : ir_jump(ir_type_discard)
    {
-      this->ir_type = ir_type_discard;
       this->condition = cond;
    }
 
@@ -1489,11 +1867,6 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-   virtual ir_discard *as_discard()
-   {
-      return this;
-   }
-
    ir_rvalue *condition;
 };
 /*@}*/
@@ -1510,7 +1883,9 @@ enum ir_texture_opcode {
    ir_txf,             /**< Texel fetch with explicit LOD */
    ir_txf_ms,           /**< Multisample texture fetch */
    ir_txs,             /**< Texture size */
-   ir_lod              /**< Texture lod query */
+   ir_lod,             /**< Texture lod query */
+   ir_tg4,             /**< Texture gather */
+   ir_query_levels      /**< Texture levels query */
 };
 
 
@@ -1535,14 +1910,17 @@ enum ir_texture_opcode {
  *      <type> <sampler> <coordinate>         <sample_index>)
  * (txs <type> <sampler> <lod>)
  * (lod <type> <sampler> <coordinate>)
+ * (tg4 <type> <sampler> <coordinate> <offset> <component>)
+ * (query_levels <type> <sampler>)
  */
 class ir_texture : public ir_rvalue {
 public:
    ir_texture(enum ir_texture_opcode op)
-      : op(op), sampler(NULL), coordinate(NULL), projector(NULL),
+      : ir_rvalue(ir_type_texture),
+        op(op), sampler(NULL), coordinate(NULL), projector(NULL),
         shadow_comparitor(NULL), offset(NULL)
    {
-      this->ir_type = ir_type_texture;
+      memset(&lod_info, 0, sizeof(lod_info));
    }
 
    virtual ir_texture *clone(void *mem_ctx, struct hash_table *) const;
@@ -1556,6 +1934,9 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual bool equals(const ir_instruction *ir,
+                       enum ir_node_type ignore = ir_type_unset) const;
+
    /**
     * Return a string representing the ir_texture_opcode.
     */
@@ -1601,6 +1982,7 @@ public:
       ir_rvalue *lod;          /**< Floating point LOD */
       ir_rvalue *bias;         /**< Floating point LOD bias */
       ir_rvalue *sample_index;  /**< MSAA sample index */
+      ir_rvalue *component;     /**< Gather component selector */
       struct {
         ir_rvalue *dPdx;       /**< Partial derivative of coordinate wrt X */
         ir_rvalue *dPdy;       /**< Partial derivative of coordinate wrt Y */
@@ -1642,11 +2024,6 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_swizzle *as_swizzle()
-   {
-      return this;
-   }
-
    /**
     * Construct an ir_swizzle from the textual representation.  Can fail.
     */
@@ -1659,6 +2036,9 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual bool equals(const ir_instruction *ir,
+                       enum ir_node_type ignore = ir_type_unset) const;
+
    bool is_lvalue() const
    {
       return val->is_lvalue() && !mask.has_duplicates;
@@ -1686,11 +2066,6 @@ class ir_dereference : public ir_rvalue {
 public:
    virtual ir_dereference *clone(void *mem_ctx, struct hash_table *) const = 0;
 
-   virtual ir_dereference *as_dereference()
-   {
-      return this;
-   }
-
    bool is_lvalue() const;
 
    /**
@@ -1698,14 +2073,11 @@ public:
     */
    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;
+protected:
+   ir_dereference(enum ir_node_type t)
+      : ir_rvalue(t)
+   {
+   }
 };
 
 
@@ -1718,10 +2090,8 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_dereference_variable *as_dereference_variable()
-   {
-      return this;
-   }
+   virtual bool equals(const ir_instruction *ir,
+                       enum ir_node_type ignore = ir_type_unset) const;
 
    /**
     * Get the variable that is ultimately referenced by an r-value
@@ -1731,15 +2101,6 @@ public:
       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
@@ -1776,10 +2137,8 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_dereference_array *as_dereference_array()
-   {
-      return this;
-   }
+   virtual bool equals(const ir_instruction *ir,
+                       enum ir_node_type ignore = ir_type_unset) const;
 
    /**
     * Get the variable that is ultimately referenced by an r-value
@@ -1789,15 +2148,6 @@ public:
       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);
@@ -1824,11 +2174,6 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_dereference_record *as_dereference_record()
-   {
-      return this;
-   }
-
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
@@ -1837,15 +2182,6 @@ public:
       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);
@@ -1866,16 +2202,18 @@ union ir_constant_data {
       int i[16];
       float f[16];
       bool b[16];
+      double d[16];
 };
 
 
 class ir_constant : public ir_rvalue {
 public:
    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);
+   ir_constant(bool b, unsigned vector_elements=1);
+   ir_constant(unsigned int u, unsigned vector_elements=1);
+   ir_constant(int i, unsigned vector_elements=1);
+   ir_constant(float f, unsigned vector_elements=1);
+   ir_constant(double d, unsigned vector_elements=1);
 
    /**
     * Construct an ir_constant from a list of ir_constant values
@@ -1903,11 +2241,6 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_constant *as_constant()
-   {
-      return this;
-   }
-
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -1915,6 +2248,9 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual bool equals(const ir_instruction *ir,
+                       enum ir_node_type ignore = ir_type_unset) const;
+
    /**
     * Get a particular component of a constant as a specific type
     *
@@ -1925,6 +2261,7 @@ public:
    /*@{*/
    bool get_bool_component(unsigned i) const;
    float get_float_component(unsigned i) const;
+   double get_double_component(unsigned i) const;
    int get_int_component(unsigned i) const;
    unsigned get_uint_component(unsigned i) const;
    /*@}*/
@@ -1962,14 +2299,27 @@ public:
     * 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_basis
+    * ir_constant::is_negative_one
     */
    bool has_value(const ir_constant *) const;
 
+   /**
+    * Return true if this ir_constant represents the given value.
+    *
+    * For vectors, this checks that each component is the given value.
+    */
+   virtual bool is_value(float f, int i) const;
    virtual bool is_zero() const;
    virtual bool is_one() const;
    virtual bool is_negative_one() const;
-   virtual bool is_basis() const;
+
+   /**
+    * Return true for constants that could be stored as 16-bit unsigned values.
+    *
+    * Note that this will return true even for signed integer ir_constants, as
+    * long as the value is non-negative and fits in 16-bits.
+    */
+   virtual bool is_uint16_constant() const;
 
    /**
     * Value of the constant.
@@ -1993,16 +2343,16 @@ private:
    ir_constant(void);
 };
 
-/*@}*/
-
 /**
  * IR instruction to emit a vertex in a geometry shader.
  */
 class ir_emit_vertex : public ir_instruction {
 public:
-   ir_emit_vertex()
+   ir_emit_vertex(ir_rvalue *stream)
+      : ir_instruction(ir_type_emit_vertex),
+        stream(stream)
    {
-      ir_type = ir_type_emit_vertex;
+      assert(stream);
    }
 
    virtual void accept(ir_visitor *v)
@@ -2010,12 +2360,19 @@ public:
       v->visit(this);
    }
 
-   virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *) const
+   virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *ht) const
    {
-      return new(mem_ctx) ir_emit_vertex();
+      return new(mem_ctx) ir_emit_vertex(this->stream->clone(mem_ctx, ht));
    }
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   int stream_id() const
+   {
+      return stream->as_constant()->value.i[0];
+   }
+
+   ir_rvalue *stream;
 };
 
 /**
@@ -2024,9 +2381,11 @@ public:
  */
 class ir_end_primitive : public ir_instruction {
 public:
-   ir_end_primitive()
+   ir_end_primitive(ir_rvalue *stream)
+      : ir_instruction(ir_type_end_primitive),
+        stream(stream)
    {
-      ir_type = ir_type_end_primitive;
+      assert(stream);
    }
 
    virtual void accept(ir_visitor *v)
@@ -2034,14 +2393,23 @@ public:
       v->visit(this);
    }
 
-   virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *) const
+   virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *ht) const
    {
-      return new(mem_ctx) ir_end_primitive();
+      return new(mem_ctx) ir_end_primitive(this->stream->clone(mem_ctx, ht));
    }
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   int stream_id() const
+   {
+      return stream->as_constant()->value.i[0];
+   }
+
+   ir_rvalue *stream;
 };
 
+/*@}*/
+
 /**
  * Apply a visitor to each IR node in a list
  */
@@ -2095,9 +2463,26 @@ _mesa_glsl_initialize_variables(exec_list *instructions,
 extern void
 _mesa_glsl_initialize_functions(_mesa_glsl_parse_state *state);
 
+extern void
+_mesa_glsl_initialize_builtin_functions();
+
+extern ir_function_signature *
+_mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state,
+                                 const char *name, exec_list *actual_parameters);
+
+extern ir_function *
+_mesa_glsl_find_builtin_function_by_name(_mesa_glsl_parse_state *state,
+                                         const char *name);
+
+extern gl_shader *
+_mesa_glsl_get_builtin_function_shader(void);
+
 extern void
 _mesa_glsl_release_functions(void);
 
+extern void
+_mesa_glsl_release_builtin_functions(void);
+
 extern void
 reparent_ir(exec_list *list, void *mem_ctx);
 
@@ -2112,20 +2497,38 @@ ir_has_call(ir_instruction *ir);
 
 extern void
 do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
-                      GLenum shader_type);
+                      gl_shader_stage shader_stage);
 
 extern char *
 prototype_string(const glsl_type *return_type, const char *name,
                 exec_list *parameters);
 
+const char *
+mode_string(const ir_variable *var);
+
+/**
+ * Built-in / reserved GL variables names start with "gl_"
+ */
+static inline bool
+is_gl_identifier(const char *s)
+{
+   return s && s[0] == 'g' && s[1] == 'l' && s[2] == '_';
+}
+
 extern "C" {
 #endif /* __cplusplus */
 
-extern void _mesa_print_ir(struct exec_list *instructions,
+extern void _mesa_print_ir(FILE *f, struct exec_list *instructions,
                            struct _mesa_glsl_parse_state *state);
 
+extern void
+fprint_ir(FILE *f, const void *instruction);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
+unsigned
+vertices_per_prim(GLenum prim);
+
 #endif /* IR_H */