summaryrefslogtreecommitdiff
path: root/gcc/halfpic.c
diff options
context:
space:
mode:
authormeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>1992-04-09 00:31:40 +0000
committermeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>1992-04-09 00:31:40 +0000
commit1d468f5b8dc064246c8216710da0bf919065fc0f (patch)
treed6984aa5591b1ab61dc874c1517039b982d1a509 /gcc/halfpic.c
parentb537df7760b36ca1f8c2cafc446677d3c17b62f5 (diff)
downloadgcc-1d468f5b8dc064246c8216710da0bf919065fc0f.tar.gz
*** empty log message ***
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@710 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/halfpic.c')
-rw-r--r--gcc/halfpic.c194
1 files changed, 165 insertions, 29 deletions
diff --git a/gcc/halfpic.c b/gcc/halfpic.c
index ca6898e806d..f2012424df7 100644
--- a/gcc/halfpic.c
+++ b/gcc/halfpic.c
@@ -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;
+
+
+/* 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;
+}
+
/* 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)
@@ -126,6 +230,30 @@ half_pic_encode (decl)
}
+/* 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
+}
+
+
/* Return whether an address is half-pic. */
int
@@ -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 */