Begin refactoring ir_dereference

Create separate subclasses of ir_dereference for variable, array, and
record dereferences.  As a side effect, array and record dereferences
no longer point to ir_variable objects directly.  Instead they each
point to an ir_dereference_variable object.

This is the first of several steps in the refactoring process.  The
intention is that ir_dereference will eventually become an abstract
base class.
diff --git a/ir.h b/ir.h
index 93b4c2b..70fe9f9 100644
--- a/ir.h
+++ b/ir.h
@@ -788,12 +788,6 @@
 
 class ir_dereference : public ir_rvalue {
 public:
-   ir_dereference(struct ir_instruction *);
-
-   ir_dereference(ir_instruction *variable, ir_rvalue *array_index);
-
-   ir_dereference(ir_instruction *variable, const char *field);
-
    virtual ir_dereference *as_dereference()
    {
       return this;
@@ -811,9 +805,9 @@
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
-   virtual ir_variable *variable_referenced();
+   virtual ir_variable *variable_referenced() = 0;
 
-   enum {
+   enum ir_deref_mode {
       ir_reference_variable,
       ir_reference_array,
       ir_reference_record
@@ -830,6 +824,63 @@
       ir_rvalue *array_index;
       const char *field;
    } selector;
+
+protected:
+   ir_dereference(ir_deref_mode mode)
+      : mode(mode)
+   {
+      /* empty */
+   }
+};
+
+
+class ir_dereference_variable : public ir_dereference {
+public:
+   ir_dereference_variable(ir_variable *var);
+
+   /**
+    * Get the variable that is ultimately referenced by an r-value
+    */
+   virtual ir_variable *variable_referenced()
+   {
+      return (ir_variable *) this->var;
+   }
+};
+
+
+class ir_dereference_array : public ir_dereference {
+public:
+   ir_dereference_array(ir_rvalue *value, ir_rvalue *array_index);
+
+   ir_dereference_array(ir_variable *var, ir_rvalue *array_index);
+
+   /**
+    * Get the variable that is ultimately referenced by an r-value
+    */
+   virtual ir_variable *variable_referenced()
+   {
+      return ((ir_rvalue *) this->var)->variable_referenced();
+   }
+
+
+private:
+   void set_array(ir_rvalue *value);
+};
+
+
+class ir_dereference_record : public ir_dereference {
+public:
+   ir_dereference_record(ir_rvalue *value, const char *field);
+
+   ir_dereference_record(ir_variable *var, const char *field);
+
+   /**
+    * Get the variable that is ultimately referenced by an r-value
+    */
+   virtual ir_variable *variable_referenced()
+   {
+      return ((ir_rvalue *) this->var)->variable_referenced();
+   }
 };