Return the rvalue of a variable decl to fix while (bool b = condition) {}
[mesa.git] / ir.h
diff --git a/ir.h b/ir.h
index 261d1924027ffac1d469de92231a3893e3554a63..2d3a8cdb0b0278bdcae863f0a18cdc3d6f6183eb 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -54,6 +54,10 @@ public:
    virtual class ir_variable *          as_variable()         { return NULL; }
    virtual class ir_dereference *       as_dereference()      { return NULL; }
    virtual class ir_rvalue *            as_rvalue()           { return NULL; }
+   virtual class ir_loop *              as_loop()             { return NULL; }
+   virtual class ir_assignment *        as_assignment()       { return NULL; }
+   virtual class ir_call *              as_call()             { return NULL; }
+   virtual class ir_return *            as_return()           { return NULL; }
    /*@}*/
 
 protected:
@@ -77,7 +81,10 @@ public:
    }
 
 protected:
-   ir_rvalue() : ir_instruction() { }
+   ir_rvalue()
+   {
+      /* empty */
+   }
 };
 
 
@@ -110,20 +117,66 @@ public:
       v->visit(this);
    }
 
+   /**
+    * Duplicate an IR variable
+    *
+    * \note
+    * This will probably be made \c virtual and moved to the base class
+    * eventually.
+    */
+   ir_variable *clone() const
+   {
+      ir_variable *var = new ir_variable(type, name);
+
+      var->max_array_access = this->max_array_access;
+      var->read_only = this->read_only;
+      var->centroid = this->centroid;
+      var->invariant = this->invariant;
+      var->mode = this->mode;
+      var->interpolation = this->interpolation;
+
+      return var;
+   }
+
    const char *name;
 
+   /**
+    * Highest element accessed with a constant expression array index
+    *
+    * Not used for non-array variables.
+    */
+   unsigned max_array_access;
+
    unsigned read_only:1;
    unsigned centroid:1;
    unsigned invariant:1;
 
    unsigned mode:3;
    unsigned interpolation:2;
+
+   /**
+    * Flag that the whole array is assignable
+    *
+    * In GLSL 1.20 and later whole arrays are assignable (and comparable for
+    * equality).  This flag enables this behavior.
+    */
+   unsigned array_lvalue:1;
+
+   /**
+    * Emit a warning if this variable is accessed.
+    */
+   const char *warn_extension;
+
+   /**
+    * Value assigned in the initializer of a variable declared "const"
+    */
+   ir_constant *constant_value;
 };
 
 
 class ir_label : public ir_instruction {
 public:
-   ir_label(const char *label);
+   ir_label(const char *label, ir_function_signature *signature);
 
    virtual void accept(ir_visitor *v)
    {
@@ -131,11 +184,16 @@ public:
    }
 
    const char *label;
+
+   ir_function_signature *signature;
 };
 
 
 /*@{*/
 class ir_function_signature : public ir_instruction {
+   /* An ir_function_signature will be part of the list of signatures in
+    * an ir_function.
+    */
 public:
    ir_function_signature(const glsl_type *return_type);
 
@@ -144,6 +202,11 @@ public:
       v->visit(this);
    }
 
+   /**
+    * Get the name of the function for which this is a signature
+    */
+   const char *function_name() const;
+
    /**
     * Function return type.
     *
@@ -152,7 +215,10 @@ public:
    const struct glsl_type *return_type;
 
    /**
-    * List of function parameters stored as ir_variable objects.
+    * List of ir_variable of function parameters.
+    *
+    * This represents the storage.  The paramaters passed in a particular
+    * call will be in ir_call::actual_paramaters.
     */
    struct exec_list parameters;
 
@@ -161,6 +227,9 @@ public:
     */
    ir_label *definition;
 
+   /** Body of instructions in the function. */
+   struct exec_list body;
+
 private:
    /** Function of which this signature is one overload. */
    class ir_function *function;
@@ -207,10 +276,15 @@ public:
 
 private:
    /**
-    * Set of overloaded functions with this name.
+    * List of ir_function_signature for each overloaded function with this name.
     */
    struct exec_list signatures;
 };
+
+inline const char *ir_function_signature::function_name() const
+{
+   return function->name;
+}
 /*@}*/
 
 
@@ -231,11 +305,56 @@ public:
    }
 
    ir_rvalue *condition;
+   /** List of ir_instruction for the body of the then branch */
    exec_list  then_instructions;
+   /** List of ir_instruction for the body of the else branch */
    exec_list  else_instructions;
 };
 
 
+/**
+ * IR instruction representing a high-level loop structure.
+ */
+class ir_loop : public ir_instruction {
+public:
+   ir_loop() : from(NULL), to(NULL), increment(NULL), counter(NULL)
+   {
+      /* empty */
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_loop *as_loop()
+   {
+      return this;
+   }
+
+   /**
+    * Get an iterator for the instructions of the loop body
+    */
+   exec_list_iterator iterator()
+   {
+      return body_instructions.iterator();
+   }
+
+   /** List of ir_instruction that make up the body of the loop. */
+   exec_list body_instructions;
+
+   /**
+    * \name Loop counter and controls
+    */
+   /*@{*/
+   ir_rvalue *from;
+   ir_rvalue *to;
+   ir_rvalue *increment;
+   ir_variable *counter;
+   /*@}*/
+};
+
+
 class ir_assignment : public ir_rvalue {
 public:
    ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition);
@@ -245,6 +364,11 @@ public:
       v->visit(this);
    }
 
+   virtual ir_assignment * as_assignment()
+   {
+      return this;
+   }
+
    /**
     * Left-hand side of the assignment.
     */
@@ -261,7 +385,9 @@ public:
    ir_rvalue *condition;
 };
 
-/* Update ir_print_visitor.cpp when updating this list. */
+/* Update ir_expression::num_operands() and ir_print_visitor.cpp when
+ * updating this list.
+*/
 enum ir_expression_operation {
    ir_unop_bit_not,
    ir_unop_logic_not,
@@ -276,6 +402,10 @@ enum ir_expression_operation {
    ir_unop_log2,
    ir_unop_f2i,      /**< Float-to-integer conversion. */
    ir_unop_i2f,      /**< Integer-to-float conversion. */
+   ir_unop_f2b,      /**< Float-to-boolean conversion */
+   ir_unop_b2f,      /**< Boolean-to-float conversion */
+   ir_unop_i2b,      /**< int-to-boolean conversion */
+   ir_unop_b2i,      /**< Boolean-to-int conversion */
    ir_unop_u2f,      /**< Unsigned-to-float conversion. */
 
    /**
@@ -319,7 +449,6 @@ enum ir_expression_operation {
    ir_binop_logic_and,
    ir_binop_logic_xor,
    ir_binop_logic_or,
-   ir_binop_logic_not,
 
    ir_binop_dot,
    ir_binop_min,
@@ -333,11 +462,15 @@ public:
    ir_expression(int op, const struct glsl_type *type,
                 ir_rvalue *, ir_rvalue *);
 
+   unsigned int get_num_operands(void);
+
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
    }
 
+   ir_expression *clone();
+
    ir_expression_operation operation;
    ir_rvalue *operands[2];
 };
@@ -349,13 +482,18 @@ public:
 class ir_call : public ir_rvalue {
 public:
    ir_call(const ir_function_signature *callee, exec_list *actual_parameters)
-      : ir_rvalue(), callee(callee)
+      : callee(callee)
    {
       assert(callee->return_type != NULL);
       type = callee->return_type;
       actual_parameters->move_nodes_to(& this->actual_parameters);
    }
 
+   virtual ir_call *as_call()
+   {
+      return this;
+   }
+
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -379,18 +517,30 @@ public:
     */
    const char *callee_name() const
    {
-      /* FINISHME: This only works for functions that have definitions. */
-      return callee->definition->label;
+      return callee->function_name();
+   }
+
+   const ir_function_signature *get_callee()
+   {
+      return callee;
    }
 
+   /**
+    * Generates an inline version of the function before @ir,
+    * returning the return value of the function.
+    */
+   ir_rvalue *generate_inline(ir_instruction *ir);
+
 private:
    ir_call()
-      : ir_rvalue(), callee(NULL)
+      : callee(NULL)
    {
       /* empty */
    }
 
    const ir_function_signature *callee;
+
+   /* List of ir_rvalue of paramaters passed in this call. */
    exec_list actual_parameters;
 };
 
@@ -404,7 +554,6 @@ private:
 class ir_jump : public ir_instruction {
 protected:
    ir_jump()
-      : ir_instruction()
    {
       /* empty */
    }
@@ -424,6 +573,11 @@ public:
       /* empty */
    }
 
+   virtual ir_return *as_return()
+   {
+      return this;
+   }
+
    ir_rvalue *get_value() const
    {
       return value;
@@ -437,6 +591,51 @@ public:
 private:
    ir_rvalue *value;
 };
+
+
+/**
+ * Jump instructions used inside loops
+ *
+ * These include \c break and \c continue.  The \c break within a loop is
+ * different from the \c break within a switch-statement.
+ *
+ * \sa ir_switch_jump
+ */
+class ir_loop_jump : public ir_jump {
+public:
+   enum jump_mode {
+      jump_break,
+      jump_continue
+   };
+
+   ir_loop_jump(ir_loop *loop, jump_mode mode)
+      : loop(loop), mode(mode)
+   {
+      /* empty */
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   bool is_break() const
+   {
+      return mode == jump_break;
+   }
+
+   bool is_continue() const
+   {
+      return mode == jump_continue;
+   }
+
+private:
+   /** Loop containing this break instruction. */
+   ir_loop *loop;
+
+   /** Mode selector for the jump instruction. */
+   enum jump_mode mode;
+};
 /*@}*/
 
 
@@ -464,6 +663,17 @@ class ir_swizzle : public ir_rvalue {
 public:
    ir_swizzle(ir_rvalue *, unsigned x, unsigned y, unsigned z, unsigned w,
               unsigned count);
+   ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask)
+      : val(val), mask(mask)
+   {
+      /* empty */
+   }
+
+   ir_swizzle *clone()
+   {
+      return new ir_swizzle(this->val, this->mask);
+   }
+
    /**
     * Construct an ir_swizzle from the textual representation.  Can fail.
     */
@@ -500,17 +710,7 @@ public:
       v->visit(this);
    }
 
-   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;
-   }
+   bool is_lvalue();
 
    enum {
       ir_reference_variable,
@@ -545,6 +745,11 @@ public:
       v->visit(this);
    }
 
+   ir_constant *clone()
+   {
+      return new ir_constant(this->type, &this->value);
+   }
+
    /**
     * Value of the constant.
     *
@@ -560,6 +765,8 @@ public:
    } value;
 };
 
+void
+visit_exec_list(exec_list *list, ir_visitor *visitor);
 
 extern void
 _mesa_glsl_initialize_variables(exec_list *instructions,