nir: Move nir_cursor to nir.h.
[mesa.git] / src / glsl / ir.h
index 2afafe4b5c7c4e6ecabc174181ba0b7baf17f258..ede8caa6e47b8b05fbb1368908102bec65aa1464 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"
@@ -78,6 +78,7 @@ enum ir_node_type {
    ir_type_discard,
    ir_type_emit_vertex,
    ir_type_end_primitive,
+   ir_type_barrier,
    ir_type_max, /**< maximum ir_type enum number, for validation */
    ir_type_unset = ir_type_max
 };
@@ -109,6 +110,31 @@ public:
    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
     *
@@ -117,41 +143,33 @@ public:
     * Additional downcast functions will be added as needed.
     */
    /*@{*/
-   class ir_rvalue *as_rvalue()
-   {
-      if (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)
-         return (class ir_rvalue *) this;
-      return NULL;
-   }
-
-   class ir_dereference *as_dereference()
-   {
-      if (ir_type == ir_type_dereference_array ||
-          ir_type == ir_type_dereference_record ||
-          ir_type == ir_type_dereference_variable)
-         return (class ir_dereference *) this;
-      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;   \
    }
 
-   class ir_jump *as_jump()
-   {
-      if (ir_type == ir_type_loop_jump ||
-          ir_type == ir_type_return ||
-          ir_type == ir_type_discard)
-         return (class ir_jump *) this;
-      return 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)
@@ -179,7 +197,8 @@ public:
     * in particular.  No support for other instruction types (assignments,
     * jumps, calls, etc.) is planned.
     */
-   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+   virtual bool equals(const ir_instruction *ir,
+                       enum ir_node_type ignore = ir_type_unset) const;
 
 protected:
    ir_instruction(enum ir_node_type t)
@@ -251,8 +270,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;
 
@@ -264,8 +282,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;
 
@@ -278,24 +295,9 @@ 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
-    *
-    * 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;
-
    /**
     * Determine if an r-value is an unsigned integer constant which can be
     * stored in 16 bits.
@@ -322,6 +324,7 @@ protected:
 enum ir_variable_mode {
    ir_var_auto = 0,     /**< Function local variables and globals. */
    ir_var_uniform,      /**< Variable declared as a uniform. */
+   ir_var_shader_storage,   /**< Variable declared as an ssbo. */
    ir_var_shader_in,
    ir_var_shader_out,
    ir_var_function_in,
@@ -359,6 +362,12 @@ enum ir_var_declaration_type {
     * 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,
 };
 
 /**
@@ -433,11 +442,14 @@ public:
    glsl_interp_qualifier determine_interpolation_mode(bool flat_shade);
 
    /**
-    * Determine whether or not a variable is part of a uniform block.
+    * Determine whether or not a variable is part of a uniform or
+    * shader storage block.
     */
-   inline bool is_in_uniform_block() const
+   inline bool is_in_buffer_block() const
    {
-      return this->data.mode == ir_var_uniform && this->interface_type != NULL;
+      return (this->data.mode == ir_var_uniform ||
+              this->data.mode == ir_var_shader_storage) &&
+             this->interface_type != NULL;
    }
 
    /**
@@ -461,11 +473,8 @@ 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;
+   }
 
    /**
     * Set this->interface_type on a newly created variable.
@@ -475,7 +484,7 @@ public:
       assert(this->interface_type == NULL);
       this->interface_type = type;
       if (this->is_interface_instance()) {
-         this->max_ifc_array_access =
+         this->u.max_ifc_array_access =
             rzalloc_array(this, unsigned, type->length);
       }
    }
@@ -487,7 +496,7 @@ public:
     */
    void change_interface_type(const struct glsl_type *type)
    {
-      if (this->max_ifc_array_access != NULL) {
+      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.
           */
@@ -504,7 +513,7 @@ public:
     */
    void reinit_interface_type(const struct glsl_type *type)
    {
-      if (this->max_ifc_array_access != NULL) {
+      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
@@ -512,10 +521,10 @@ public:
           * zero.
           */
          for (unsigned i = 0; i < this->interface_type->length; i++)
-            assert(this->max_ifc_array_access[i] == 0);
+            assert(this->u.max_ifc_array_access[i] == 0);
 #endif
-         ralloc_free(this->max_ifc_array_access);
-         this->max_ifc_array_access = NULL;
+         ralloc_free(this->u.max_ifc_array_access);
+         this->u.max_ifc_array_access = NULL;
       }
       this->interface_type = NULL;
       init_interface_type(type);
@@ -527,27 +536,80 @@ public:
    }
 
    /**
-    * Declared type of the variable
+    * Get the max_ifc_array_access pointer
+    *
+    * A "set" function is not needed because the array is dynmically allocated
+    * as necessary.
     */
-   const struct glsl_type *type;
+   inline unsigned *get_max_ifc_array_access()
+   {
+      assert(this->data._num_state_slots == 0);
+      return this->u.max_ifc_array_access;
+   }
+
+   inline unsigned get_num_state_slots() const
+   {
+      assert(!this->is_interface_instance()
+             || this->data._num_state_slots == 0);
+      return this->data._num_state_slots;
+   }
+
+   inline void set_num_state_slots(unsigned n)
+   {
+      assert(!this->is_interface_instance()
+             || n == 0);
+      this->data._num_state_slots = n;
+   }
+
+   inline ir_state_slot *get_state_slots()
+   {
+      return this->is_interface_instance() ? NULL : this->u.state_slots;
+   }
+
+   inline const ir_state_slot *get_state_slots() const
+   {
+      return this->is_interface_instance() ? NULL : this->u.state_slots;
+   }
+
+   inline ir_state_slot *allocate_state_slots(unsigned n)
+   {
+      assert(!this->is_interface_instance());
+
+      this->u.state_slots = ralloc_array(this, ir_state_slot, n);
+      this->data._num_state_slots = 0;
+
+      if (this->u.state_slots != NULL)
+         this->data._num_state_slots = n;
+
+      return this->u.state_slots;
+   }
+
+   inline bool is_name_ralloced() const
+   {
+      return this->name != ir_variable::tmp_name;
+   }
 
    /**
-    * Declared name of the variable
+    * Enable emitting extension warnings for this variable
     */
-   const char *name;
+   void enable_extension_warning(const char *extension);
 
    /**
-    * 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.
+    * Get the extension warning string for this variable
     *
-    * For variables whose type is not an interface block, this pointer is
-    * NULL.
+    * If warnings are not enabled, \c NULL is returned.
     */
-   unsigned *max_ifc_array_access;
+   const char *get_extension_warning() const;
+
+   /**
+    * Declared type of the variable
+    */
+   const struct glsl_type *type;
+
+   /**
+    * Declared name of the variable
+    */
+   const char *name;
 
    struct ir_variable_data {
 
@@ -560,7 +622,9 @@ public:
       unsigned read_only:1;
       unsigned centroid:1;
       unsigned sample:1;
+      unsigned patch:1;
       unsigned invariant:1;
+      unsigned precise:1;
 
       /**
        * Has this variable been used for reading or writing?
@@ -658,6 +722,11 @@ public:
        */
       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.
@@ -676,13 +745,66 @@ public:
        */
       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.
+       */
+      unsigned index: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;
+      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;
 
       /**
        * Storage location of the base of this variable
@@ -705,39 +827,17 @@ public:
       int location;
 
       /**
-       * output index for dual source blending.
-       */
-      int index;
-
-      /**
-       * Initial binding point for a sampler or UBO.
-       *
-       * For array types, this represents the binding point for the first element.
+       * Vertex stream output identifier.
        */
-      int binding;
+      unsigned stream;
 
       /**
        * Location an atomic counter is stored at.
        */
       struct {
-         unsigned buffer_index;
          unsigned offset;
       } atomic;
 
-      /**
-       * ARB_shader_image_load_store qualifiers.
-       */
-      struct {
-         bool read_only; /**< "readonly" qualifier. */
-         bool write_only; /**< "writeonly" qualifier. */
-         bool coherent;
-         bool _volatile;
-         bool restrict_flag;
-
-         /** Image internal format if specified explicitly, otherwise GL_NONE. */
-         GLenum format;
-      } image;
-
       /**
        * Highest element accessed with a constant expression array index
        *
@@ -745,29 +845,12 @@ public:
        */
       unsigned max_array_access;
 
+      /**
+       * Allow (only) ir_variable direct access private members.
+       */
+      friend class ir_variable;
    } data;
 
-   /**
-    * 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. */
-   /*@}*/
-
-   /**
-    * Emit a warning if this variable is accessed.
-    */
-   const char *warn_extension;
-
    /**
     * Value assigned in the initializer of a variable declared "const"
     */
@@ -784,6 +867,33 @@ 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.
@@ -791,6 +901,30 @@ private:
     * \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;
 };
 
 /**
@@ -962,6 +1096,7 @@ public:
     */
    ir_function_signature *matching_signature(_mesa_glsl_parse_state *state,
                                              const exec_list *actual_param,
+                                             bool allow_builtins,
                                             bool *match_is_exact);
 
    /**
@@ -969,7 +1104,8 @@ public:
     * conversions into account.
     */
    ir_function_signature *matching_signature(_mesa_glsl_parse_state *state,
-                                             const exec_list *actual_param);
+                                             const exec_list *actual_param,
+                                             bool allow_builtins);
 
    /**
     * Find a signature that exactly matches a set of actual parameters without
@@ -990,6 +1126,21 @@ public:
     * List of ir_function_signature for each overloaded function with this name.
     */
    struct exec_list signatures;
+
+   /**
+    * is this function a subroutine type declaration
+    * e.g. subroutine void type1(float arg1);
+    */
+   bool is_subroutine;
+
+   /**
+    * is this function associated to a subroutine type
+    * e.g. subroutine (type1, type2) function_name { function_body };
+    * would have num_subroutine_types 2,
+    * and pointers to the type1 and type2 types.
+    */
+   int num_subroutine_types;
+   const struct glsl_type **subroutine_types;
 };
 
 inline const char *ir_function_signature::function_name() const
@@ -1154,6 +1305,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" */
@@ -1177,8 +1335,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] */
    /*@}*/
 
    /**
@@ -1186,7 +1342,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,
    /*@}*/
 
    /**
@@ -1225,12 +1385,33 @@ 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,
 
+   ir_unop_subroutine_to_int,
+   /**
+    * 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,
@@ -1348,10 +1529,26 @@ 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.
@@ -1435,7 +1632,8 @@ public:
     */
    ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1, ir_rvalue *op2);
 
-   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+   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;
 
@@ -1514,7 +1712,18 @@ public:
    ir_call(ir_function_signature *callee,
           ir_dereference_variable *return_deref,
           exec_list *actual_parameters)
-      : ir_instruction(ir_type_call), return_deref(return_deref), callee(callee)
+      : ir_instruction(ir_type_call), return_deref(return_deref), callee(callee), sub_var(NULL), array_idx(NULL)
+   {
+      assert(callee->return_type != NULL);
+      actual_parameters->move_nodes_to(& this->actual_parameters);
+      this->use_builtin = callee->is_builtin();
+   }
+
+   ir_call(ir_function_signature *callee,
+          ir_dereference_variable *return_deref,
+          exec_list *actual_parameters,
+          ir_variable *var, ir_rvalue *array_idx)
+      : ir_instruction(ir_type_call), return_deref(return_deref), callee(callee), sub_var(var), array_idx(array_idx)
    {
       assert(callee->return_type != NULL);
       actual_parameters->move_nodes_to(& this->actual_parameters);
@@ -1562,6 +1771,14 @@ public:
 
    /** Should this call only bind to a built-in function? */
    bool use_builtin;
+
+   /*
+    * ARB_shader_subroutine support -
+    * the subroutine uniform variable and array index
+    * rvalue to be used in the lowering pass later.
+    */
+   ir_variable *sub_var;
+   ir_rvalue *array_idx;
 };
 
 
@@ -1746,7 +1963,8 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+   virtual bool equals(const ir_instruction *ir,
+                       enum ir_node_type ignore = ir_type_unset) const;
 
    /**
     * Return a string representing the ir_texture_opcode.
@@ -1847,7 +2065,8 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+   virtual bool equals(const ir_instruction *ir,
+                       enum ir_node_type ignore = ir_type_unset) const;
 
    bool is_lvalue() const
    {
@@ -1900,7 +2119,8 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+   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
@@ -1946,7 +2166,8 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+   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
@@ -2010,6 +2231,7 @@ union ir_constant_data {
       int i[16];
       float f[16];
       bool b[16];
+      double d[16];
 };
 
 
@@ -2020,6 +2242,7 @@ public:
    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
@@ -2054,7 +2277,8 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+   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
@@ -2066,6 +2290,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;
    /*@}*/
@@ -2103,7 +2328,7 @@ 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;
 
@@ -2116,7 +2341,6 @@ public:
    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.
@@ -2153,9 +2377,11 @@ private:
  */
 class ir_emit_vertex : public ir_instruction {
 public:
-   ir_emit_vertex()
-      : ir_instruction(ir_type_emit_vertex)
+   ir_emit_vertex(ir_rvalue *stream)
+      : ir_instruction(ir_type_emit_vertex),
+        stream(stream)
    {
+      assert(stream);
    }
 
    virtual void accept(ir_visitor *v)
@@ -2163,12 +2389,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;
 };
 
 /**
@@ -2177,9 +2410,11 @@ public:
  */
 class ir_end_primitive : public ir_instruction {
 public:
-   ir_end_primitive()
-      : ir_instruction(ir_type_end_primitive)
+   ir_end_primitive(ir_rvalue *stream)
+      : ir_instruction(ir_type_end_primitive),
+        stream(stream)
    {
+      assert(stream);
    }
 
    virtual void accept(ir_visitor *v)
@@ -2187,9 +2422,39 @@ 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;
+};
+
+/**
+ * IR instruction for tessellation control and compute shader barrier.
+ */
+class ir_barrier : public ir_instruction {
+public:
+   ir_barrier()
+      : ir_instruction(ir_type_barrier)
+   {
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_barrier *clone(void *mem_ctx, struct hash_table *) const
+   {
+      return new(mem_ctx) ir_barrier();
    }
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
@@ -2257,6 +2522,10 @@ 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);