Support stuff for register allocation.


git-svn-id: svn://svn.valgrind.org/vex/trunk@28 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/host_regs.c b/host_regs.c
index 2810896..745f228 100644
--- a/host_regs.c
+++ b/host_regs.c
@@ -49,3 +49,116 @@
    }
 }
 
+
+/*---------------------------------------------------------*/
+/*--- Helpers for recording reg usage (for reg-alloc)   ---*/
+/*---------------------------------------------------------*/
+
+void ppHRegUsage ( FILE* f, HRegUsage* tab )
+{
+   Int   i;
+   Char* str;
+   fprintf(f, "HRegUsage {\n");
+   for (i = 0; i < tab->n_used; i++) {
+      switch (tab->mode[i]) {
+         case HRmRead:   str = "Read   "; break;
+         case HRmWrite:  str = "Write  "; break;
+         case HRmModify: str = "Modify "; break;
+         default: panic("ppHRegUsage");
+      }
+      fprintf(f, "   %s ", str);
+      ppHReg(f, tab->hreg[i]);
+      fprintf(f, "\n");
+   }
+   fprintf(f, "}\n");
+}
+
+
+void initHRegUsage ( HRegUsage* tab )
+{
+   tab->n_used = 0;
+}
+
+
+/* Add a register to a usage table.  Combine incoming read uses with
+   existing write uses into a modify use, and vice versa.  Do not
+   create duplicate entries -- each reg should only be mentioned once.  
+*/
+void addHRegUsage ( HRegUsage* tab, HReg reg, HRegMode mode )
+{
+   Int i;
+   /* Find it ... */
+   for (i = 0; i < tab->n_used; i++)
+      if (tab->hreg[i] == reg)
+         break;
+   if (i == tab->n_used) {
+      /* Not found, add new entry. */
+      assert(tab->n_used+1 < N_HREG_USAGE);
+      tab->hreg[tab->n_used] = reg;
+      tab->mode[tab->n_used] = mode;
+      tab->n_used++;
+   } else {
+      /* Found: combine or ignore. */
+      if (tab->mode[i] == mode)
+         return; /* duplicate, ignore */
+      if (mode == HRmModify) {
+         tab->mode[i] = HRmModify;
+         return; /* modify mode makes previous mode irrelevant */
+      }
+      assert( (mode == HRmRead && tab->mode[i] == HRmWrite)
+              || (mode == HRmWrite && tab->mode[i] == HRmRead) );
+      tab->mode[i] = HRmModify;
+   }
+}
+
+
+/*---------------------------------------------------------*/
+/*--- Indicating register remappings (for reg-alloc)    ---*/
+/*---------------------------------------------------------*/
+
+void ppHRegRemap ( FILE* f, HRegRemap* map )
+{
+   Int   i;
+   fprintf(f, "HRegRemap {\n");
+   for (i = 0; i < map->n_used; i++) {
+      fprintf(f, "   ");
+      ppHReg(f, tab->orig[i]);
+      fprintf(f, "  -->  ");
+      ppHReg(f, tab->replacement[i]);
+      fprintf(f, "\n");
+   }
+   fprintf(f, "}\n");
+}
+
+
+void initHRegRemap ( HRegRemap* map )
+{
+   map->n_used = 0;
+}
+
+
+void addToHRegRemap ( HRegRemap* map, HReg orig, HReg replacement )
+{
+   Int i;
+   for (i = 0; i < map->n_used; i++)
+      if (map->orig[i] == orig)
+         panic("addToHRegMap: duplicate entry");
+   assert(map->n_used+1 < N_HREG_REMAP);
+   map->orig[map->n_used]        = orig;
+   map->replacement[map->n_used] = replacement;
+   map->n_used++;
+}
+
+
+HReg lookupHRegRemap ( HRegRemap* map, HReg orig )
+{
+   Int i;
+   for (i = 0; i < map->n_used; i++)
+      if (map->orig[i] == orig)
+         return map->replacement[i];
+   panic("lookupHRegRemap: not found");
+}
+
+/*---------------------------------------------------------------*/
+/*---                                             host_regs.c ---*/
+/*---------------------------------------------------------------*/