i965: Rename brw_disasm to brw_disassemble_inst.
[mesa.git] / src / glsl / ir.h
index 85b4d057f5e2411edba208ef47d1a12e4f76d7d0..ef4a12d60ef1220cb46b010af2d80fde2104316b 100644 (file)
@@ -86,6 +86,7 @@ enum ir_node_type {
    ir_type_max /**< maximum ir_type enum number, for validation */
 };
 
+
 /**
  * Base class of all IR instructions
  */
@@ -105,6 +106,7 @@ 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;
@@ -133,11 +135,22 @@ public:
    virtual class ir_return *            as_return()           { return NULL; }
    virtual class ir_if *                as_if()               { return NULL; }
    virtual class ir_swizzle *           as_swizzle()          { return NULL; }
+   virtual class ir_texture *           as_texture()          { return NULL; }
    virtual class ir_constant *          as_constant()         { return NULL; }
    virtual class ir_discard *           as_discard()          { return NULL; }
    virtual class ir_jump *              as_jump()             { return NULL; }
    /*@}*/
 
+   /**
+    * IR equality method: Return true if the referenced instruction would
+    * return the same value as this one.
+    *
+    * This intended to be used for CSE and algebraic optimizations, on rvalues
+    * in particular.  No support for other instruction types (assignments,
+    * jumps, calls, etc.) is planned.
+    */
+   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+
 protected:
    ir_instruction()
    {
@@ -252,6 +265,13 @@ public:
     */
    virtual bool is_basis() const;
 
+   /**
+    * Determine if an r-value is an unsigned integer constant which can be
+    * stored in 16 bits.
+    *
+    * \sa ir_constant::is_uint16_constant.
+    */
+   virtual bool is_uint16_constant() const { return false; }
 
    /**
     * Return a generic value of error_type.
@@ -282,6 +302,34 @@ enum ir_variable_mode {
    ir_var_mode_count   /**< Number of variable modes */
 };
 
+/**
+ * Enum keeping track of how a variable was declared.  For error checking of
+ * the gl_PerVertex redeclaration rules.
+ */
+enum ir_var_declaration_type {
+   /**
+    * Normal declaration (for most variables, this means an explicit
+    * declaration.  Exception: temporaries are always implicitly declared, but
+    * they still use ir_var_declared_normally).
+    *
+    * Note: an ir_variable that represents a named interface block uses
+    * ir_var_declared_normally.
+    */
+   ir_var_declared_normally = 0,
+
+   /**
+    * Variable was explicitly declared (or re-declared) in an unnamed
+    * interface block.
+    */
+   ir_var_declared_in_block,
+
+   /**
+    * Variable is an implicitly declared built-in that has not been explicitly
+    * re-declared by the shader.
+    */
+   ir_var_declared_implicitly,
+};
+
 /**
  * \brief Layout qualifiers for gl_FragDepth.
  *
@@ -363,7 +411,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;
    }
 
    /**
@@ -431,7 +479,7 @@ public:
    void reinit_interface_type(const struct glsl_type *type)
    {
       if (this->max_ifc_array_access != NULL) {
-#ifndef _NDEBUG
+#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
@@ -462,13 +510,6 @@ public:
     */
    const char *name;
 
-   /**
-    * Highest element accessed with a constant expression array index
-    *
-    * Not used for non-array variables.
-    */
-   unsigned max_array_access;
-
    /**
     * For variables which satisfy the is_interface_instance() predicate, this
     * points to an array of integers such that if the ith member of the
@@ -482,169 +523,203 @@ public:
     */
    unsigned *max_ifc_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;
-
-   /**
-    * 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;
-
-   /**
-    * 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;
-   /*@}*/
+   struct ir_variable_data {
 
-   /**
-    * 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;
+      /**
+       * 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;
+
+      /**
+       * 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;
 
-   /**
-    * 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;
+      /**
+       * 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;
 
-   /**
-    * Does this variable have an initializer?
-    *
-    * This is used by the linker to cross-validiate initializers of global
-    * variables.
-    */
-   unsigned has_initializer:1;
+      /**
+       * Storage class of the variable.
+       *
+       * \sa ir_variable_mode
+       */
+      unsigned mode:4;
 
-   /**
-    * 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;
+      /**
+       * Interpolation mode for shader inputs / outputs
+       *
+       * \sa ir_variable_interpolation
+       */
+      unsigned interpolation:2;
 
-   /**
-    * 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;
+      /**
+       * \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;
+
+      /**
+       * 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;
 
-   /**
-    * 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;
+      /**
+       * 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;
+
+      /**
+       * 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 this variable was created by lowering a named interface
-    * block which was an array.
-    *
-    * Note that this variable and \c from_named_ifc_block_nonarray will never
-    * both be non-zero.
-    */
-   unsigned from_named_ifc_block_array:1;
+      /**
+       * \brief Layout qualifier for gl_FragDepth.
+       *
+       * 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;
+
+      /**
+       * 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;
 
-   /**
-    * \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;
+      /**
+       * output index for dual source blending.
+       */
+      int index;
 
-   /**
-    * 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;
+      /**
+       * Initial binding point for a sampler or UBO.
+       *
+       * For array types, this represents the binding point for the first element.
+       */
+      int binding;
 
-   /**
-    * output index for dual source blending.
-    */
-   int index;
+      /**
+       * Location an atomic counter is stored at.
+       */
+      struct {
+         unsigned buffer_index;
+         unsigned offset;
+      } atomic;
 
-   /**
-    * Initial binding point for a sampler or UBO.
-    *
-    * For array types, this represents the binding point for the first element.
-    */
-   int binding;
+      /**
+       * 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
+       *
+       * Not used for non-array variables.
+       */
+      unsigned max_array_access;
 
-   /**
-    * Location an atomic counter is stored at.
-    */
-   struct {
-      unsigned buffer_index;
-      unsigned offset;
-   } atomic;
+   } data;
 
    /**
     * Built-in state that backs this uniform
@@ -787,6 +862,12 @@ public:
    /** Whether or not this function signature is a built-in. */
    bool is_builtin() const;
 
+   /**
+    * Whether or not this function is an intrinsic to be implemented
+    * by the driver.
+    */
+   bool is_intrinsic;
+
    /** Whether or not a built-in is available for this shader. */
    bool is_builtin_available(const _mesa_glsl_parse_state *state) const;
 
@@ -854,14 +935,6 @@ 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.
@@ -959,44 +1032,8 @@ public:
       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;
-   /*@}*/
 };
 
 
@@ -1398,6 +1435,8 @@ public:
       return this;
    }
 
+   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+
    virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
 
    /**
@@ -1426,6 +1465,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.
     */
@@ -1487,14 +1538,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.
     */
@@ -1725,8 +1768,15 @@ public:
       v->visit(this);
    }
 
+   virtual ir_texture *as_texture()
+   {
+      return this;
+   }
+
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+
    /**
     * Return a string representing the ir_texture_opcode.
     */
@@ -1831,6 +1881,8 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+
    bool is_lvalue() const
    {
       return val->is_lvalue() && !mask.has_duplicates;
@@ -1869,15 +1921,6 @@ public:
     * Get the variable that is ultimately referenced by an r-value
     */
    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;
 };
 
 
@@ -1895,6 +1938,8 @@ public:
       return this;
    }
 
+   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
@@ -1903,15 +1948,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
@@ -1953,6 +1989,8 @@ public:
       return this;
    }
 
+   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
@@ -1961,15 +1999,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);
@@ -2009,15 +2038,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);
@@ -2087,6 +2107,8 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+
    /**
     * Get a particular component of a constant as a specific type
     *
@@ -2138,11 +2160,25 @@ public:
     */
    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.
     *
@@ -2165,8 +2201,6 @@ private:
    ir_constant(void);
 };
 
-/*@}*/
-
 /**
  * IR instruction to emit a vertex in a geometry shader.
  */
@@ -2214,6 +2248,8 @@ public:
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 };
 
+/*@}*/
+
 /**
  * Apply a visitor to each IR node in a list
  */
@@ -2274,6 +2310,9 @@ extern ir_function_signature *
 _mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state,
                                  const char *name, exec_list *actual_parameters);
 
+extern gl_shader *
+_mesa_glsl_get_builtin_function_shader(void);
+
 extern void
 _mesa_glsl_release_functions(void);
 
@@ -2294,18 +2333,24 @@ 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);
+
 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