Merge remote branch 'origin/master' into pipe-video
[mesa.git] / src / glsl / ir.h
index 65026ef1f5bd0da2c29099312beff39683b9be26..f2f902c0a775939a89e915cef913d909ece30134 100644 (file)
 #ifndef IR_H
 #define IR_H
 
-#include <cstdio>
-#include <cstdlib>
-
-extern "C" {
-#include <talloc.h>
-}
+#include <stdio.h>
+#include <stdlib.h>
 
+#include "ralloc.h"
+#include "glsl_types.h"
 #include "list.h"
 #include "ir_visitor.h"
 #include "ir_hierarchical_visitor.h"
 
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
-#endif
+/**
+ * \defgroup IR Intermediate representation nodes
+ *
+ * @{
+ */
 
-struct ir_program {
-   void *bong_hits;
+/**
+ * Class tags
+ *
+ * Each concrete class derived from \c ir_instruction has a value in this
+ * enumerant.  The value for the type is stored in \c ir_instruction::ir_type
+ * by the constructor.  While using type tags is not very C++, it is extremely
+ * convenient.  For example, during debugging you can simply inspect
+ * \c ir_instruction::ir_type to find out the actual type of the object.
+ *
+ * In addition, it is possible to use a switch-statement based on \c
+ * \c ir_instruction::ir_type to select different behavior for different object
+ * types.  For functions that have only slight differences for several object
+ * 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_expression,
+   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_max /**< maximum ir_type enum number, for validation */
 };
 
 /**
@@ -50,16 +86,16 @@ struct ir_program {
  */
 class ir_instruction : public exec_node {
 public:
+   enum ir_node_type ir_type;
    const struct glsl_type *type;
 
-   class ir_constant *constant_expression_value();
-
    /** ir_print_visitor helper for debugging. */
    void print(void) const;
 
    virtual void accept(ir_visitor *) = 0;
    virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0;
-   virtual ir_instruction *clone(struct hash_table *ht) const = 0;
+   virtual ir_instruction *clone(void *mem_ctx,
+                                struct hash_table *ht) const = 0;
 
    /**
     * \name IR instruction downcast functions
@@ -74,6 +110,7 @@ public:
    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_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; }
@@ -82,23 +119,31 @@ public:
    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; }
    /*@}*/
 
 protected:
    ir_instruction()
    {
-      /* empty */
+      ir_type = ir_type_unset;
+      type = NULL;
    }
 };
 
 
 class ir_rvalue : public ir_instruction {
 public:
+   virtual ir_rvalue *clone(void *mem_ctx, struct hash_table *) const = 0;
+
+   virtual ir_constant *constant_expression_value() = 0;
+
    virtual ir_rvalue * as_rvalue()
    {
       return this;
    }
 
+   ir_rvalue *as_rvalue_to_saturate();
+
    virtual bool is_lvalue()
    {
       return false;
@@ -127,20 +172,59 @@ public:
       return NULL;
    }
 
+   /**
+    * Determine if an r-value has the value zero
+    *
+    * 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 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
+    */
+   virtual bool is_zero() const;
+
+   /**
+    * Determine if an r-value has the value one
+    *
+    * 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 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
+    */
+   virtual bool is_one() const;
+
+   /**
+    * Determine if an r-value has the value negative one
+    *
+    * 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 all elements set to the value
+    * negative one.  For boolean times, the result is always \c false.
+    *
+    * \sa ir_constant::has_value, ir_rvalue::is_zero, ir_rvalue::is_one
+    */
+   virtual bool is_negative_one() const;
+
 protected:
-   ir_rvalue()
-   {
-      /* empty */
-   }
+   ir_rvalue();
 };
 
 
+/**
+ * Variable storage classes
+ */
 enum ir_variable_mode {
-   ir_var_auto = 0,
-   ir_var_uniform,
+   ir_var_auto = 0,     /**< Function local variables and globals. */
+   ir_var_uniform,      /**< Variable declared as a uniform. */
    ir_var_in,
    ir_var_out,
-   ir_var_inout
+   ir_var_inout,
+   ir_var_const_in,    /**< "in" param that must be a constant expression */
+   ir_var_system_value, /**< Ex: front-face, instance-id, etc. */
+   ir_var_temporary    /**< Temporary variable generated during compilation. */
 };
 
 enum ir_variable_interpolation {
@@ -149,12 +233,31 @@ enum ir_variable_interpolation {
    ir_var_noperspective
 };
 
+/**
+ * \brief Layout qualifiers for gl_FragDepth.
+ *
+ * The AMD_conservative_depth extension allows gl_FragDepth to be redeclared
+ * with a layout qualifier.
+ */
+enum ir_depth_layout {
+    ir_depth_layout_none, /**< No depth layout is specified. */
+    ir_depth_layout_any,
+    ir_depth_layout_greater,
+    ir_depth_layout_less,
+    ir_depth_layout_unchanged
+};
+
+/**
+ * \brief Convert depth layout qualifier to string.
+ */
+const char*
+depth_layout_string(ir_depth_layout layout);
 
 class ir_variable : public ir_instruction {
 public:
-   ir_variable(const struct glsl_type *, const char *);
+   ir_variable(const struct glsl_type *, const char *, ir_variable_mode);
 
-   virtual ir_instruction *clone(struct hash_table *ht) const;
+   virtual ir_variable *clone(void *mem_ctx, struct hash_table *ht) const;
 
    virtual ir_variable *as_variable()
    {
@@ -172,10 +275,10 @@ public:
    /**
     * Get the string value for the interpolation qualifier
     *
-    * \return
-    * If none of \c shader_in or \c shader_out is set, an empty string will
-    * be returned.  Otherwise the string that would be used in a shader to
-    * specify \c mode will be returned.
+    * \return The string that would be used in a shader to specify \c
+    * mode will be returned.
+    *
+    * This function should only be used on a shader input or output variable.
     */
    const char *interpolation_string() const;
 
@@ -187,6 +290,9 @@ public:
     */
    unsigned component_slots() const;
 
+   /**
+    * Delcared name of the variable
+    */
    const char *name;
 
    /**
@@ -196,17 +302,37 @@ public:
     */
    unsigned max_array_access;
 
+   /**
+    * 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;
-   /** If the variable is initialized outside of the scope of the shader */
-   unsigned shader_in:1;
+
    /**
-    * If the variable value is later used outside of the scope of the shader.
+    * 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.
     */
-   unsigned shader_out:1;
+   unsigned used:1;
 
+   /**
+    * Storage class of the variable.
+    *
+    * \sa ir_variable_mode
+    */
    unsigned mode:3;
+
+   /**
+    * Interpolation mode for shader inputs / outputs
+    *
+    * \sa ir_variable_interpolation
+    */
    unsigned interpolation:2;
 
    /**
@@ -217,6 +343,31 @@ public:
     */
    unsigned array_lvalue:1;
 
+   /**
+    * \name ARB_fragment_coord_conventions
+    * @{
+    */
+   unsigned origin_upper_left:1;
+   unsigned pixel_center_integer: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;
+
+   /**
+    * 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;
+
    /**
     * Storage location of the base of this variable
     *
@@ -258,7 +409,10 @@ class ir_function_signature : public ir_instruction {
 public:
    ir_function_signature(const glsl_type *return_type);
 
-   virtual ir_instruction *clone(struct hash_table *ht) const;
+   virtual ir_function_signature *clone(void *mem_ctx,
+                                       struct hash_table *ht) const;
+   ir_function_signature *clone_prototype(void *mem_ctx,
+                                         struct hash_table *ht) const;
 
    virtual void accept(ir_visitor *v)
    {
@@ -272,6 +426,23 @@ public:
     */
    const char *function_name() const;
 
+   /**
+    * Get a handle to the function for which this is a signature
+    *
+    * There is no setter function, this function returns a \c const pointer,
+    * and \c ir_function_signature::_function is private for a reason.  The
+    * only way to make a connection between a function and function signature
+    * is via \c ir_function::add_signature.  This helps ensure that certain
+    * invariants (i.e., a function signature is in the list of signatures for
+    * its \c _function) are met.
+    *
+    * \sa ir_function::add_signature
+    */
+   inline const class ir_function *function() const
+   {
+      return this->_function;
+   }
+
    /**
     * Check whether the qualifiers match between this signature's parameters
     * and the supplied parameter list.  If not, returns the name of the first
@@ -304,12 +475,15 @@ public:
    /** Whether or not this function has a body (which may be empty). */
    unsigned is_defined:1;
 
+   /** Whether or not this function signature is a built-in. */
+   unsigned is_builtin:1;
+
    /** Body of instructions in the function. */
    struct exec_list body;
 
 private:
    /** Function of which this signature is one overload. */
-   class ir_function *function;
+   class ir_function *_function;
 
    friend class ir_function;
 };
@@ -324,7 +498,7 @@ class ir_function : public ir_instruction {
 public:
    ir_function(const char *name);
 
-   virtual ir_instruction *clone(struct hash_table *ht) const;
+   virtual ir_function *clone(void *mem_ctx, struct hash_table *ht) const;
 
    virtual ir_function *as_function()
    {
@@ -340,8 +514,8 @@ public:
 
    void add_signature(ir_function_signature *sig)
    {
-      sig->function = this;
-      signatures.push_tail(sig);
+      sig->_function = this;
+      this->signatures.push_tail(sig);
    }
 
    /**
@@ -356,20 +530,22 @@ public:
     * Find a signature that matches a set of actual parameters, taking implicit
     * conversions into account.
     */
-   const ir_function_signature *matching_signature(exec_list *actual_param);
+   ir_function_signature *matching_signature(const exec_list *actual_param);
 
    /**
     * Find a signature that exactly matches a set of actual parameters without
     * any implicit type conversions.
     */
-   ir_function_signature *exact_matching_signature(exec_list *actual_ps);
+   ir_function_signature *exact_matching_signature(const exec_list *actual_ps);
 
    /**
     * Name of the function.
     */
    const char *name;
 
-private:
+   /** Whether or not this function has a signature that isn't a built-in. */
+   bool has_user_signature();
+
    /**
     * List of ir_function_signature for each overloaded function with this name.
     */
@@ -378,7 +554,7 @@ private:
 
 inline const char *ir_function_signature::function_name() const
 {
-   return function->name;
+   return this->_function->name;
 }
 /*@}*/
 
@@ -391,10 +567,10 @@ public:
    ir_if(ir_rvalue *condition)
       : condition(condition)
    {
-      /* empty */
+      ir_type = ir_type_if;
    }
 
-   virtual ir_instruction *clone(struct hash_table *ht) const;
+   virtual ir_if *clone(void *mem_ctx, struct hash_table *ht) const;
 
    virtual ir_if *as_if()
    {
@@ -421,12 +597,9 @@ public:
  */
 class ir_loop : public ir_instruction {
 public:
-   ir_loop() : from(NULL), to(NULL), increment(NULL), counter(NULL)
-   {
-      /* empty */
-   }
+   ir_loop();
 
-   virtual ir_instruction *clone(struct hash_table *ht) const;
+   virtual ir_loop *clone(void *mem_ctx, struct hash_table *ht) const;
 
    virtual void accept(ir_visitor *v)
    {
@@ -453,21 +626,51 @@ public:
 
    /**
     * \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;
-   ir_rvalue *to;
+   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;
    /*@}*/
 };
 
 
-class ir_assignment : public ir_rvalue {
+class ir_assignment : public ir_instruction {
 public:
    ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition);
 
-   virtual ir_instruction *clone(struct hash_table *ht) const;
+   /**
+    * Construct an assignment with an explicit write mask
+    *
+    * \note
+    * Since a write mask is supplied, the LHS must already be a bare
+    * \c ir_dereference.  The cannot be any swizzles in the LHS.
+    */
+   ir_assignment(ir_dereference *lhs, ir_rvalue *rhs, ir_rvalue *condition,
+                unsigned write_mask);
+
+   virtual ir_assignment *clone(void *mem_ctx, struct hash_table *ht) const;
+
+   virtual ir_constant *constant_expression_value();
 
    virtual void accept(ir_visitor *v)
    {
@@ -481,10 +684,32 @@ public:
       return this;
    }
 
+   /**
+    * Get a whole variable written by an assignment
+    *
+    * If the LHS of the assignment writes a whole variable, the variable is
+    * returned.  Otherwise \c NULL is returned.  Examples of whole-variable
+    * assignment are:
+    *
+    *  - Assigning to a scalar
+    *  - Assigning to all components of a vector
+    *  - Whole array (or matrix) assignment
+    *  - Whole structure assignment
+    */
+   ir_variable *whole_variable_written();
+
+   /**
+    * Set the LHS of an assignment
+    */
+   void set_lhs(ir_rvalue *lhs);
+
    /**
     * Left-hand side of the assignment.
+    *
+    * This should be treated as read only.  If you need to set the LHS of an
+    * assignment, use \c ir_assignment::set_lhs.
     */
-   ir_rvalue *lhs;
+   ir_dereference *lhs;
 
    /**
     * Value being assigned
@@ -495,6 +720,24 @@ public:
     * Optional condition for the assignment.
     */
    ir_rvalue *condition;
+
+
+   /**
+    * Component mask written
+    *
+    * For non-vector types in the LHS, this field will be zero.  For vector
+    * types, a bit will be set for each component that is written.  Note that
+    * for \c vec2 and \c vec3 types only the lower bits will ever be set.
+    *
+    * A partially-set write mask means that each enabled channel gets
+    * the value from a consecutive channel of the rhs.  For example,
+    * to write just .xyw of gl_FrontColor with color:
+    *
+    * (assign (constant bool (1)) (xyw)
+    *     (var_ref gl_FragColor)
+    *     (swiz xyw (var_ref color)))
+    */
+   unsigned write_mask:4;
 };
 
 /* Update ir_expression::num_operands() and operator_strs when
@@ -509,8 +752,8 @@ enum ir_expression_operation {
    ir_unop_rcp,
    ir_unop_rsq,
    ir_unop_sqrt,
-   ir_unop_exp,
-   ir_unop_log,
+   ir_unop_exp,      /**< Log base e on gentype */
+   ir_unop_log,             /**< Natural log on gentype */
    ir_unop_exp2,
    ir_unop_log2,
    ir_unop_f2i,      /**< Float-to-integer conversion. */
@@ -520,6 +763,7 @@ enum ir_expression_operation {
    ir_unop_i2b,      /**< int-to-boolean conversion */
    ir_unop_b2i,      /**< Boolean-to-int conversion */
    ir_unop_u2f,      /**< Unsigned-to-float conversion. */
+   ir_unop_any,
 
    /**
     * \name Unary floating-point rounding operations.
@@ -528,6 +772,8 @@ enum ir_expression_operation {
    ir_unop_trunc,
    ir_unop_ceil,
    ir_unop_floor,
+   ir_unop_fract,
+   ir_unop_round_even,
    /*@}*/
 
    /**
@@ -536,6 +782,8 @@ 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] */
    /*@}*/
 
    /**
@@ -546,14 +794,31 @@ enum ir_expression_operation {
    ir_unop_dFdy,
    /*@}*/
 
+   ir_unop_noise,
+
+   /**
+    * A sentinel marking the last of the unary operations.
+    */
+   ir_last_unop = ir_unop_noise,
+
    ir_binop_add,
    ir_binop_sub,
    ir_binop_mul,
    ir_binop_div,
+
+   /**
+    * Takes one of two combinations of arguments:
+    *
+    * - mod(vecN, vecN)
+    * - mod(vecN, float)
+    *
+    * Does not take integer types.
+    */
    ir_binop_mod,
 
    /**
-    * \name Binary comparison operators
+    * \name Binary comparison operators which return a boolean vector.
+    * The type of both operands must be equal.
     */
    /*@{*/
    ir_binop_less,
@@ -562,6 +827,16 @@ enum ir_expression_operation {
    ir_binop_gequal,
    ir_binop_equal,
    ir_binop_nequal,
+   /**
+    * Returns single boolean for whether all components of operands[0]
+    * equal the components of operands[1].
+    */
+   ir_binop_all_equal,
+   /**
+    * Returns single boolean for whether any component of operands[0]
+    * is not equal to the corresponding component of operands[1].
+    */
+   ir_binop_any_nequal,
    /*@}*/
 
    /**
@@ -583,20 +858,69 @@ enum ir_expression_operation {
    ir_binop_min,
    ir_binop_max,
 
-   ir_binop_pow
+   ir_binop_pow,
+
+   /**
+    * A sentinel marking the last of the binary operations.
+    */
+   ir_last_binop = ir_binop_pow,
+
+   ir_quadop_vector,
+
+   /**
+    * A sentinel marking the last of all operations.
+    */
+   ir_last_opcode = ir_last_binop
 };
 
 class ir_expression : public ir_rvalue {
 public:
+   /**
+    * Constructor for unary operation expressions
+    */
+   ir_expression(int op, const struct glsl_type *type, ir_rvalue *);
+   ir_expression(int op, ir_rvalue *);
+
+   /**
+    * Constructor for binary operation expressions
+    */
    ir_expression(int op, const struct glsl_type *type,
                 ir_rvalue *, ir_rvalue *);
+   ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1);
+
+   /**
+    * Constructor for quad operator expressions
+    */
+   ir_expression(int op, const struct glsl_type *type,
+                ir_rvalue *, ir_rvalue *, ir_rvalue *, ir_rvalue *);
 
-   virtual ir_instruction *clone(struct hash_table *ht) const;
+   virtual ir_expression *as_expression()
+   {
+      return this;
+   }
+
+   virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
 
+   /**
+    * Attempt to constant-fold the expression
+    *
+    * If the expression cannot be constant folded, this method will return
+    * \c NULL.
+    */
+   virtual ir_constant *constant_expression_value();
+
+   /**
+    * Determine the number of operands used by an expression
+    */
    static unsigned int get_num_operands(ir_expression_operation);
+
+   /**
+    * Determine the number of operands used by an expression
+    */
    unsigned int get_num_operands() const
    {
-      return get_num_operands(operation);
+      return (this->operation == ir_quadop_vector)
+        ? this->type->vector_elements : get_num_operands(operation);
    }
 
    /**
@@ -604,6 +928,12 @@ public:
     */
    const char *operator_string();
 
+   /**
+    * Return a string representing this expression's operator.
+    */
+   static const char *operator_string(ir_expression_operation);
+
+
    /**
     * Do a reverse-lookup to translate the given string into an operator.
     */
@@ -617,7 +947,7 @@ public:
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
    ir_expression_operation operation;
-   ir_rvalue *operands[2];
+   ir_rvalue *operands[4];
 };
 
 
@@ -626,15 +956,18 @@ public:
  */
 class ir_call : public ir_rvalue {
 public:
-   ir_call(const ir_function_signature *callee, exec_list *actual_parameters)
+   ir_call(ir_function_signature *callee, exec_list *actual_parameters)
       : callee(callee)
    {
+      ir_type = ir_type_call;
       assert(callee->return_type != NULL);
       type = callee->return_type;
       actual_parameters->move_nodes_to(& this->actual_parameters);
    }
 
-   virtual ir_instruction *clone(struct hash_table *ht) const;
+   virtual ir_call *clone(void *mem_ctx, struct hash_table *ht) const;
+
+   virtual ir_constant *constant_expression_value();
 
    virtual ir_call *as_call()
    {
@@ -651,7 +984,7 @@ public:
    /**
     * Get a generic ir_call object when an error occurs
     *
-    * Any allocation will be performed with 'ctx' as talloc owner.
+    * Any allocation will be performed with 'ctx' as ralloc owner.
     */
    static ir_call *get_error_instruction(void *ctx);
 
@@ -671,28 +1004,36 @@ public:
       return callee->function_name();
    }
 
-   const ir_function_signature *get_callee()
+   /**
+    * Get the function signature bound to this function call
+    */
+   ir_function_signature *get_callee()
    {
       return callee;
    }
 
+   /**
+    * Set the function call target
+    */
+   void set_callee(ir_function_signature *sig);
+
    /**
     * Generates an inline version of the function before @ir,
     * returning the return value of the function.
     */
    ir_rvalue *generate_inline(ir_instruction *ir);
 
+   /* List of ir_rvalue of paramaters passed in this call. */
+   exec_list actual_parameters;
+
 private:
    ir_call()
       : callee(NULL)
    {
-      /* empty */
+      this->ir_type = ir_type_call;
    }
 
-   const ir_function_signature *callee;
-
-   /* List of ir_rvalue of paramaters passed in this call. */
-   exec_list actual_parameters;
+   ir_function_signature *callee;
 };
 
 
@@ -706,7 +1047,7 @@ class ir_jump : public ir_instruction {
 protected:
    ir_jump()
    {
-      /* empty */
+      ir_type = ir_type_unset;
    }
 };
 
@@ -715,16 +1056,16 @@ public:
    ir_return()
       : value(NULL)
    {
-      /* empty */
+      this->ir_type = ir_type_return;
    }
 
    ir_return(ir_rvalue *value)
       : value(value)
    {
-      /* empty */
+      this->ir_type = ir_type_return;
    }
 
-   virtual ir_instruction *clone(struct hash_table *) const;
+   virtual ir_return *clone(void *mem_ctx, struct hash_table *) const;
 
    virtual ir_return *as_return()
    {
@@ -764,11 +1105,12 @@ public:
 
    ir_loop_jump(jump_mode mode)
    {
+      this->ir_type = ir_type_loop_jump;
       this->mode = mode;
       this->loop = loop;
    }
 
-   virtual ir_instruction *clone(struct hash_table *) const;
+   virtual ir_loop_jump *clone(void *mem_ctx, struct hash_table *) const;
 
    virtual void accept(ir_visitor *v)
    {
@@ -793,6 +1135,40 @@ private:
    /** Loop containing this break instruction. */
    ir_loop *loop;
 };
+
+/**
+ * IR instruction representing discard statements.
+ */
+class ir_discard : public ir_jump {
+public:
+   ir_discard()
+   {
+      this->ir_type = ir_type_discard;
+      this->condition = NULL;
+   }
+
+   ir_discard(ir_rvalue *cond)
+   {
+      this->ir_type = ir_type_discard;
+      this->condition = cond;
+   }
+
+   virtual ir_discard *clone(void *mem_ctx, struct hash_table *ht) const;
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   virtual ir_discard *as_discard()
+   {
+      return this;
+   }
+
+   ir_rvalue *condition;
+};
 /*@}*/
 
 
@@ -800,11 +1176,11 @@ private:
  * Texture sampling opcodes used in ir_texture
  */
 enum ir_texture_opcode {
-   ir_tex,             /* Regular texture look-up */
-   ir_txb,             /* Texture look-up with LOD bias */
-   ir_txl,             /* Texture look-up with explicit LOD */
-   ir_txd,             /* Texture look-up with partial derivatvies */
-   ir_txf              /* Texel fetch with explicit LOD */
+   ir_tex,             /**< Regular texture look-up */
+   ir_txb,             /**< Texture look-up with LOD bias */
+   ir_txl,             /**< Texture look-up with explicit LOD */
+   ir_txd,             /**< Texture look-up with partial derivatvies */
+   ir_txf              /**< Texel fetch with explicit LOD */
 };
 
 
@@ -815,26 +1191,28 @@ enum ir_texture_opcode {
  * selected from \c ir_texture_opcodes.  In the printed IR, these will
  * appear as:
  *
- *                              Texel offset
- *                              |       Projection divisor
- *                              |       |   Shadow comparitor
- *                              |       |   |
- *                              v       v   v
- * (tex (sampler) (coordinate) (0 0 0) (1) ( ))
- * (txb (sampler) (coordinate) (0 0 0) (1) ( ) (bias))
- * (txl (sampler) (coordinate) (0 0 0) (1) ( ) (lod))
- * (txd (sampler) (coordinate) (0 0 0) (1) ( ) (dPdx dPdy))
- * (txf (sampler) (coordinate) (0 0 0)         (lod))
+ *                             Texel offset (0 or an expression)
+ *                             | Projection divisor
+ *                             | |  Shadow comparitor
+ *                             | |  |
+ *                             v v  v
+ * (tex <sampler> <coordinate> 0 1 ( ))
+ * (txb <sampler> <coordinate> 0 1 ( ) <bias>)
+ * (txl <sampler> <coordinate> 0 1 ( ) <lod>)
+ * (txd <sampler> <coordinate> 0 1 ( ) (dPdx dPdy))
+ * (txf <sampler> <coordinate> 0       <lod>)
  */
 class ir_texture : public ir_rvalue {
 public:
    ir_texture(enum ir_texture_opcode op)
-      : op(op), projector(NULL), shadow_comparitor(NULL)
+      : op(op), projector(NULL), shadow_comparitor(NULL), offset(NULL)
    {
-      /* empty */
+      this->ir_type = ir_type_texture;
    }
 
-   virtual ir_instruction *clone(struct hash_table *) const;
+   virtual ir_texture *clone(void *mem_ctx, struct hash_table *) const;
+
+   virtual ir_constant *constant_expression_value();
 
    virtual void accept(ir_visitor *v)
    {
@@ -881,8 +1259,8 @@ public:
     */
    ir_rvalue *shadow_comparitor;
 
-   /** Explicit texel offsets. */
-   signed char offsets[3];
+   /** Texel offset. */
+   ir_rvalue *offset;
 
    union {
       ir_rvalue *lod;          /**< Floating point LOD */
@@ -924,7 +1302,9 @@ public:
 
    ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask);
 
-   virtual ir_instruction *clone(struct hash_table *) const;
+   virtual ir_swizzle *clone(void *mem_ctx, struct hash_table *) const;
+
+   virtual ir_constant *constant_expression_value();
 
    virtual ir_swizzle *as_swizzle()
    {
@@ -968,6 +1348,8 @@ private:
 
 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;
@@ -986,7 +1368,10 @@ class ir_dereference_variable : public ir_dereference {
 public:
    ir_dereference_variable(ir_variable *var);
 
-   virtual ir_instruction *clone(struct hash_table *) const;
+   virtual ir_dereference_variable *clone(void *mem_ctx,
+                                         struct hash_table *) const;
+
+   virtual ir_constant *constant_expression_value();
 
    virtual ir_dereference_variable *as_dereference_variable()
    {
@@ -1032,7 +1417,10 @@ public:
 
    ir_dereference_array(ir_variable *var, ir_rvalue *array_index);
 
-   virtual ir_instruction *clone(struct hash_table *) const;
+   virtual ir_dereference_array *clone(void *mem_ctx,
+                                      struct hash_table *) const;
+
+   virtual ir_constant *constant_expression_value();
 
    virtual ir_dereference_array *as_dereference_array()
    {
@@ -1068,7 +1456,10 @@ public:
 
    ir_dereference_record(ir_variable *var, const char *field);
 
-   virtual ir_instruction *clone(struct hash_table *) const;
+   virtual ir_dereference_record *clone(void *mem_ctx,
+                                       struct hash_table *) const;
+
+   virtual ir_constant *constant_expression_value();
 
    /**
     * Get the variable that is ultimately referenced by an r-value
@@ -1126,7 +1517,14 @@ public:
     */
    ir_constant(const ir_constant *c, unsigned i);
 
-   virtual ir_instruction *clone(struct hash_table *) const;
+   /**
+    * Return a new ir_constant of the specified type containing all zeros.
+    */
+   static ir_constant *zero(void *mem_ctx, const glsl_type *type);
+
+   virtual ir_constant *clone(void *mem_ctx, struct hash_table *) const;
+
+   virtual ir_constant *constant_expression_value();
 
    virtual ir_constant *as_constant()
    {
@@ -1154,13 +1552,22 @@ public:
    unsigned get_uint_component(unsigned i) const;
    /*@}*/
 
+   ir_constant *get_array_element(unsigned i) const;
+
    ir_constant *get_record_field(const char *name);
 
    /**
     * 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
     */
    bool has_value(const ir_constant *) const;
 
+   virtual bool is_zero() const;
+   virtual bool is_one() const;
+   virtual bool is_negative_one() const;
+
    /**
     * Value of the constant.
     *
@@ -1170,6 +1577,10 @@ public:
     */
    union ir_constant_data value;
 
+   /* Array elements */
+   ir_constant **array_elements;
+
+   /* Structure fields */
    exec_list components;
 
 private:
@@ -1179,17 +1590,51 @@ private:
    ir_constant(void);
 };
 
+/*@}*/
+
+/**
+ * Apply a visitor to each IR node in a list
+ */
 void
 visit_exec_list(exec_list *list, ir_visitor *visitor);
 
+/**
+ * Validate invariants on each IR node in a list
+ */
 void validate_ir_tree(exec_list *instructions);
 
+/**
+ * Make a clone of each IR instruction in a list
+ *
+ * \param in   List of IR instructions that are to be cloned
+ * \param out  List to hold the cloned instructions
+ */
+void
+clone_ir_list(void *mem_ctx, exec_list *out, const exec_list *in);
+
 extern void
 _mesa_glsl_initialize_variables(exec_list *instructions,
                                struct _mesa_glsl_parse_state *state);
 
 extern void
-_mesa_glsl_initialize_functions(exec_list *instructions,
-                               struct _mesa_glsl_parse_state *state);
+_mesa_glsl_initialize_functions(_mesa_glsl_parse_state *state);
+
+extern void
+_mesa_glsl_release_functions(void);
+
+extern void
+reparent_ir(exec_list *list, void *mem_ctx);
+
+struct glsl_symbol_table;
+
+extern void
+import_prototypes(const exec_list *source, exec_list *dest,
+                 struct glsl_symbol_table *symbols, void *mem_ctx);
+
+extern bool
+ir_has_call(ir_instruction *ir);
+
+extern void
+do_set_program_inouts(exec_list *instructions, struct gl_program *prog);
 
 #endif /* IR_H */