*** empty log message ***
authorMichael Meissner <meissner@gcc.gnu.org>
Thu, 9 Apr 1992 00:31:40 +0000 (00:31 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Thu, 9 Apr 1992 00:31:40 +0000 (00:31 +0000)
From-SVN: r710

gcc/halfpic.c
gcc/halfpic.h

index ca6898e806da7f43175ca8759a35bc7bf6489512..f2012424df7fd808dc33f242c792697822139f9d 100644 (file)
@@ -34,6 +34,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "tree.h"
 #include "rtl.h"
 #include <stdio.h>
+#include <string.h>
 #include "obstack.h"
 
 #define obstack_chunk_alloc xmalloc
@@ -42,6 +43,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 extern char *xmalloc ();
 extern void  free ();
 extern rtx eliminate_constant_term ();
+extern void assemble_name ();
+extern void output_addr_const ();
 
 int flag_half_pic;             /* Global half-pic flag.  */
 
@@ -51,8 +54,10 @@ static struct obstack half_pic_obstack;
 /* List of pointers created to pic references.  */
 
 struct all_refs {
+  struct all_refs *hash_next;  /* next name in hash chain */
   struct all_refs *next;       /* next name created */
-  rtx             ref;         /* reference rtl */
+  int             external_p;  /* name is an external reference */
+  int             pointer_p;   /* pointer created.  */
   char           *ref_name;    /* reference name to ptr to real_name */
   int             ref_len;     /* reference name length */
   char           *real_name;   /* real function/data name */
@@ -61,6 +66,94 @@ struct all_refs {
 
 static struct all_refs *half_pic_names;
 
+static char *half_pic_prefix;
+static int   half_pic_prefix_len;
+
+\f
+/* Return the hash bucket of a name or NULL.  The hash chain is
+   organized as a self reorganizing circularly linked chain.  It is
+   assumed that any name passed to use will never be reallocated.  For
+   names in SYMBOL_REF's this is true, because the names are allocated
+   on the permanent obstack.  */
+
+#ifndef MAX_HASH_TABLE
+#define MAX_HASH_TABLE 1009
+#endif
+
+#define HASHBITS 30
+
+static struct all_refs *
+half_pic_hash (name, len, create_p)
+     char *name;               /* name to hash */
+     int len;                  /* length of the name (or 0 to call strlen) */
+     int create_p;             /* != 0 to create new hash bucket if new */
+{
+  static struct all_refs *hash_table[MAX_HASH_TABLE];
+  static struct all_refs  zero_all_refs;
+
+  unsigned char *uname;
+  int hash;
+  int i;
+  int ch;
+  struct all_refs *first;
+  struct all_refs *ptr;
+
+  if (len == 0)
+    len = strlen (name);
+
+  /* Compute hash code */
+  uname = (unsigned char *)name;
+  ch = uname[0];
+  hash = len * 613 + ch;
+  for (i = 1; i < len; i += 2)
+    hash = (hash * 613) + uname[i];
+
+  hash &= (1 << HASHBITS) - 1;
+  hash %= MAX_HASH_TABLE;
+
+  /* See if the name is in the hash table.  */
+  ptr = first = hash_table[hash];
+  if (ptr)
+    {
+      do
+       {
+         if (len == ptr->real_len
+             && ch == *(ptr->real_name)
+             && !strcmp (name, ptr->real_name))
+           {
+             hash_table[hash] = ptr;
+             return ptr;
+           }
+
+         ptr = ptr->hash_next;
+       }
+      while (ptr != first);
+    }
+
+  /* name not in hash table.  */
+  if (!create_p)
+    return (struct all_refs *)0;
+
+  ptr = (struct all_refs *) obstack_alloc (&half_pic_obstack, sizeof (struct all_refs));
+  *ptr = zero_all_refs;
+
+  ptr->real_name = name;
+  ptr->real_len  = len;
+
+  /* Update circular links.  */
+  if (first == (struct all_refs *)0)
+    ptr->hash_next = ptr;
+
+  else
+    {
+      ptr->hash_next = first->hash_next;
+      first->hash_next = ptr;
+    }
+
+  hash_table[hash] = ptr;
+  return ptr;
+}
+
 \f
 /* Do any half-pic initializations.  */
 
@@ -68,6 +161,8 @@ void
 half_pic_init ()
 {
   flag_half_pic = TRUE;
+  half_pic_prefix = HALF_PIC_PREFIX;
+  half_pic_prefix_len = strlen (half_pic_prefix);
   obstack_init (&half_pic_obstack);
 }
 
@@ -86,8 +181,12 @@ half_pic_finish (stream)
   data_section ();
   for (; p != 0; p = p->next)
     {
-      ASM_OUTPUT_LABEL (stream, p->ref_name);
-      ASM_OUTPUT_INT (stream, gen_rtx (SYMBOL_REF, Pmode, p->real_name));
+      /* Emit the pointer if used.  */
+      if (p->pointer_p)
+       {
+         ASM_OUTPUT_LABEL (stream, p->ref_name);
+         ASM_OUTPUT_INT (stream, gen_rtx (SYMBOL_REF, Pmode, p->real_name));
+       }
     }
 }
 
@@ -100,6 +199,7 @@ half_pic_encode (decl)
 {
   enum tree_code code = TREE_CODE (decl);
   tree asm_name;
+  struct all_refs *ptr;
 
   if (!flag_half_pic)
     return;
@@ -115,7 +215,11 @@ half_pic_encode (decl)
   if (!asm_name)
     return;
 
-  TREE_PUBLIC (asm_name) = TRUE;
+  ptr = half_pic_hash (IDENTIFIER_POINTER (asm_name),
+                      IDENTIFIER_LENGTH (asm_name),
+                      TRUE);
+
+  ptr->external_p = TRUE;
 
 #ifdef HALF_PIC_DEBUG
   if (HALF_PIC_DEBUG)
@@ -125,6 +229,30 @@ half_pic_encode (decl)
 #endif
 }
 
+\f
+/* Mark that an object is now local, and no longer needs half-pic.  */
+
+void
+half_pic_declare (name)
+     char *name;
+{
+  struct all_refs *ptr;
+
+  if (!flag_half_pic)
+    return;
+
+  ptr = half_pic_hash (name, 0, FALSE);
+  if (!ptr)
+    return;
+
+  ptr->external_p = FALSE;
+
+#ifdef HALF_PIC_DEBUG
+  if (HALF_PIC_DEBUG)
+    fprintf (stderr, "\n========== Half_pic_declare %s\n", name);
+#endif
+}
+
 \f
 /* Return whether an address is half-pic.  */
 
@@ -133,13 +261,17 @@ half_pic_address_p (addr)
      rtx addr;
 {
   char *name;
-  tree tname;
+  int len;
+  struct all_refs *ptr;
 
   if (!flag_half_pic)
     return FALSE;
 
   switch (GET_CODE (addr))
     {
+    default:
+      break;
+
     case CONST:
       {
        rtx offset = const0_rtx;
@@ -161,8 +293,20 @@ half_pic_address_p (addr)
       if (name[0] == '*')
        return FALSE;
 
-      tname = get_identifier (name);
-      if (TREE_PUBLIC (tname))
+      /* If this is a reference to the actual half-pic pointer, it
+        is obviously not half-pic.  */
+
+      len = strlen (name);
+      if (len > half_pic_prefix_len
+         && half_pic_prefix[0] == name[0]
+         && !strncmp (name, half_pic_prefix, half_pic_prefix_len))
+       return FALSE;
+
+      ptr = half_pic_hash (name, len, FALSE);
+      if (ptr == (struct all_refs *)0)
+       return FALSE;
+
+      if (ptr->external_p)
        {
 #ifdef HALF_PIC_DEBUG
          if (HALF_PIC_DEBUG)
@@ -184,40 +328,32 @@ half_pic_ptr (operand)
      rtx operand;
 {
   char *name;
-  tree tname;
   struct all_refs *p;
-  int ch;
   int len;
-  int prefix_len;
 
   if (GET_CODE (operand) != SYMBOL_REF)
     return operand;
 
   name = XSTR (operand, 0);
   len = strlen (name);
-  ch = name[0];
-  for (p = half_pic_names; p != 0; p = p->next)
-    {
-      if (ch == *(p->ref_name)
-         && len == p->real_len
-         && !strcmp (name, p->real_name))
-       return p->ref;
-    }
+  p = half_pic_hash (name, len, FALSE);
+  if (p == (struct all_refs *)0 || !p->external_p)
+    return operand;
 
-  p = (struct all_refs *) obstack_alloc (&half_pic_obstack, sizeof (struct all_refs));
+  if (!p->pointer_p)
+    {                          /* first time, create pointer */
+      obstack_grow (&half_pic_obstack, half_pic_prefix, half_pic_prefix_len);
+      obstack_grow (&half_pic_obstack, name, len);
 
-  prefix_len = strlen (HALF_PIC_PREFIX);
-  obstack_grow (&half_pic_obstack, HALF_PIC_PREFIX, prefix_len);
-  obstack_grow (&half_pic_obstack, name, len);
+      p->next      = half_pic_names;
+      p->ref_name  = (char *) obstack_finish (&half_pic_obstack);
+      p->ref_len   = len + half_pic_prefix_len;
+      p->pointer_p = TRUE;
 
-  p->next      = half_pic_names;
-  p->real_name = name;
-  p->real_len  = len;
-  p->ref_len   = len + prefix_len;
-  p->ref_name  = (char *) obstack_finish (&half_pic_obstack);
-  p->ref       = gen_rtx (SYMBOL_REF, Pmode, p->ref_name);
+      half_pic_names = p;
+    }
 
-  half_pic_names = p;
+  return gen_rtx (SYMBOL_REF, Pmode, p->ref_name);
 }
 
 #endif /* HALF_PIC_INIT */
index 0b8a61c76d86da6d04613e63f5f78da38208326a..b972ff9d17d912d293017167902da21efa92cb89 100644 (file)
@@ -19,6 +19,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 extern int  flag_half_pic;             /* Global half-pic flag.  */
 extern void half_pic_encode ();                /* encode whether half-pic */
+extern void half_pic_declare ();       /* declare object local */
 extern void half_pic_init ();          /* half_pic initialization */
 extern void half_pic_finish ();                /* half_pic termination */
 extern int  half_pic_address_p ();     /* true if an address is half-pic */
@@ -29,6 +30,7 @@ extern struct rtx_def *half_pic_ptr ();       /* return RTX for half-pic pointer */
 
 #define HALF_PIC_P()           (flag_half_pic)
 #define HALF_PIC_ENCODE(DECL)  half_pic_encode (DECL)
+#define HALF_PIC_DECLARE(NAME) half_pic_declare (NAME)
 #define HALF_PIC_INIT()                half_pic_init ()
 #define HALF_PIC_FINISH(STREAM)        half_pic_finish (STREAM)
 #define HALF_PIC_ADDRESS_P(X)  half_pic_address_p (X)