Make ir_function::signatures private
[mesa.git] / ir.h
diff --git a/ir.h b/ir.h
index b0c2f14e12920df28f520b932e5a916dfa500aa2..261d1924027ffac1d469de92231a3893e3554a63 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -33,46 +33,51 @@ struct ir_program {
    void *bong_hits;
 };
 
-
-enum ir_opcodes {
-   ir_op_var_decl,
-   ir_op_assign,
-   ir_op_expression,
-   ir_op_dereference,
-   ir_op_jump,
-   ir_op_label,
-   ir_op_constant,
-   ir_op_func_sig,
-   ir_op_func,
-   ir_op_call,
-};
-
 /**
  * Base class of all IR instructions
  */
 class ir_instruction : public exec_node {
 public:
-   unsigned mode;
    const struct glsl_type *type;
 
+   class ir_constant *constant_expression_value();
    virtual void accept(ir_visitor *) = 0;
 
+   /**
+    * \name IR instruction downcast functions
+    *
+    * These functions either cast the object to a derived class or return
+    * \c NULL if the object's type does not match the specified derived class.
+    * Additional downcast functions will be added as needed.
+    */
+   /*@{*/
+   virtual class ir_variable *          as_variable()         { return NULL; }
+   virtual class ir_dereference *       as_dereference()      { return NULL; }
+   virtual class ir_rvalue *            as_rvalue()           { return NULL; }
+   /*@}*/
+
 protected:
-   ir_instruction(int mode)
-      : mode(mode)
+   ir_instruction()
    {
       /* empty */
    }
+};
 
-private:
-   /**
-    * Dummy constructor to catch bad constructors in derived classes.
-    *
-    * Every derived must use the constructor that sets the instructions
-    * mode.  Having the \c void constructor private prevents derived classes
-    * from accidentally doing the wrong thing.
-    */
-   ir_instruction(void);
+
+class ir_rvalue : public ir_instruction {
+public:
+   virtual ir_rvalue * as_rvalue()
+   {
+      return this;
+   }
+
+   virtual bool is_lvalue()
+   {
+      return false;
+   }
+
+protected:
+   ir_rvalue() : ir_instruction() { }
 };
 
 
@@ -90,10 +95,16 @@ enum ir_varaible_interpolation {
    ir_var_noperspective
 };
 
+
 class ir_variable : public ir_instruction {
 public:
    ir_variable(const struct glsl_type *, const char *);
 
+   virtual ir_variable *as_variable()
+   {
+      return this;
+   }
+
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -149,6 +160,12 @@ public:
     * Pointer to the label that begins the function definition.
     */
    ir_label *definition;
+
+private:
+   /** Function of which this signature is one overload. */
+   class ir_function *function;
+
+   friend class ir_function;
 };
 
 
@@ -164,6 +181,20 @@ public:
       v->visit(this);
    }
 
+   void add_signature(ir_function_signature *sig)
+   {
+      sig->function = 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.
     */
@@ -174,6 +205,7 @@ public:
     */
    const char *name;
 
+private:
    /**
     * Set of overloaded functions with this name.
     */
@@ -181,13 +213,32 @@ public:
 };
 /*@}*/
 
-class ir_expression;
-class ir_dereference;
 
-class ir_assignment : public ir_instruction {
+/**
+ * IR instruction representing high-level if-statements
+ */
+class ir_if : public ir_instruction {
+public:
+   ir_if(ir_rvalue *condition)
+      : condition(condition)
+   {
+      /* empty */
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   ir_rvalue *condition;
+   exec_list  then_instructions;
+   exec_list  else_instructions;
+};
+
+
+class ir_assignment : public ir_rvalue {
 public:
-   ir_assignment(ir_instruction *lhs, ir_instruction *rhs,
-                ir_expression *condition);
+   ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition);
 
    virtual void accept(ir_visitor *v)
    {
@@ -197,22 +248,20 @@ public:
    /**
     * Left-hand side of the assignment.
     */
-   ir_dereference *lhs;
+   ir_rvalue *lhs;
 
    /**
     * Value being assigned
-    *
-    * This should be either \c ir_op_expression or \c ir_op_dereference.
     */
-   ir_instruction *rhs;
+   ir_rvalue *rhs;
 
    /**
     * Optional condition for the assignment.
     */
-   ir_expression *condition;
+   ir_rvalue *condition;
 };
 
-
+/* Update ir_print_visitor.cpp when updating this list. */
 enum ir_expression_operation {
    ir_unop_bit_not,
    ir_unop_logic_not,
@@ -220,10 +269,14 @@ enum ir_expression_operation {
    ir_unop_abs,
    ir_unop_rcp,
    ir_unop_rsq,
+   ir_unop_sqrt,
    ir_unop_exp,
    ir_unop_log,
+   ir_unop_exp2,
+   ir_unop_log2,
    ir_unop_f2i,      /**< Float-to-integer conversion. */
    ir_unop_i2f,      /**< Integer-to-float conversion. */
+   ir_unop_u2f,      /**< Unsigned-to-float conversion. */
 
    /**
     * \name Unary floating-point rounding operations.
@@ -275,10 +328,10 @@ enum ir_expression_operation {
    ir_binop_pow
 };
 
-class ir_expression : public ir_instruction {
+class ir_expression : public ir_rvalue {
 public:
    ir_expression(int op, const struct glsl_type *type,
-                ir_instruction *, ir_instruction *);
+                ir_rvalue *, ir_rvalue *);
 
    virtual void accept(ir_visitor *v)
    {
@@ -286,17 +339,17 @@ public:
    }
 
    ir_expression_operation operation;
-   ir_instruction *operands[2];
+   ir_rvalue *operands[2];
 };
 
 
 /**
  * IR instruction representing a function call
  */
-class ir_call : public ir_instruction {
+class ir_call : public ir_rvalue {
 public:
    ir_call(const ir_function_signature *callee, exec_list *actual_parameters)
-      : ir_instruction(ir_op_call), callee(callee)
+      : ir_rvalue(), callee(callee)
    {
       assert(callee->return_type != NULL);
       type = callee->return_type;
@@ -313,9 +366,26 @@ public:
     */
    static ir_call *get_error_instruction();
 
+   /**
+    * 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.
+    */
+   const char *callee_name() const
+   {
+      /* FINISHME: This only works for functions that have definitions. */
+      return callee->definition->label;
+   }
+
 private:
    ir_call()
-      : ir_instruction(ir_op_call), callee(NULL)
+      : ir_rvalue(), callee(NULL)
    {
       /* empty */
    }
@@ -334,7 +404,7 @@ private:
 class ir_jump : public ir_instruction {
 protected:
    ir_jump()
-      : ir_instruction(ir_op_jump)
+      : ir_instruction()
    {
       /* empty */
    }
@@ -348,13 +418,13 @@ public:
       /* empty */
    }
 
-   ir_return(ir_expression *value)
+   ir_return(ir_rvalue *value)
       : value(value)
    {
       /* empty */
    }
 
-   ir_expression *get_value() const
+   ir_rvalue *get_value() const
    {
       return value;
    }
@@ -365,7 +435,7 @@ public:
    }
 
 private:
-   ir_expression *value;
+   ir_rvalue *value;
 };
 /*@}*/
 
@@ -379,7 +449,7 @@ struct ir_swizzle_mask {
    /**
     * Number of components in the swizzle.
     */
-   unsigned num_components:2;
+   unsigned num_components:3;
 
    /**
     * Does the swizzle contain duplicate components?
@@ -389,21 +459,58 @@ struct ir_swizzle_mask {
    unsigned has_duplicates:1;
 };
 
-class ir_dereference : public ir_instruction {
+
+class ir_swizzle : public ir_rvalue {
+public:
+   ir_swizzle(ir_rvalue *, unsigned x, unsigned y, unsigned z, unsigned w,
+              unsigned count);
+   /**
+    * Construct an ir_swizzle from the textual representation.  Can fail.
+    */
+   static ir_swizzle *create(ir_rvalue *, const char *, unsigned vector_length);
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   bool is_lvalue()
+   {
+      return val->is_lvalue() && !mask.has_duplicates;
+   }
+
+   ir_rvalue *val;
+   ir_swizzle_mask mask;
+};
+
+
+class ir_dereference : public ir_rvalue {
 public:
    ir_dereference(struct ir_instruction *);
 
+   ir_dereference(ir_instruction *variable, ir_rvalue *array_index);
+
+   virtual ir_dereference *as_dereference()
+   {
+      return this;
+   }
+
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
    }
 
-   /**
-    * Setting the swizzle of a derefernce
-    */
-   void set_swizzle(unsigned x, unsigned y, unsigned z, unsigned w,
-                   unsigned count);
+   bool is_lvalue()
+   {
+      if (var == NULL)
+        return false;
 
+      ir_variable *const as_var = var->as_variable();
+      if (as_var == NULL)
+        return false;
+
+      return !as_var->read_only;
+   }
 
    enum {
       ir_reference_variable,
@@ -414,21 +521,24 @@ public:
    /**
     * Object being dereferenced.
     *
-    * Must be either an \c ir_variable or an \c ir_dereference.
+    * Must be either an \c ir_variable or an \c ir_rvalue.
     */
    ir_instruction *var;
 
    union {
-      ir_expression *array_index;
+      ir_rvalue *array_index;
       const char *field;
-      struct ir_swizzle_mask swizzle;
    } selector;
 };
 
 
-class ir_constant : public ir_instruction {
+class ir_constant : public ir_rvalue {
 public:
    ir_constant(const struct glsl_type *type, const void *data);
+   ir_constant(bool b);
+   ir_constant(unsigned int u);
+   ir_constant(int i);
+   ir_constant(float f);
 
    virtual void accept(ir_visitor *v)
    {
@@ -455,4 +565,8 @@ 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);
+
 #endif /* IR_H */