From: Michael Meissner Date: Thu, 9 Apr 1992 00:31:40 +0000 (+0000) Subject: *** empty log message *** X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=58891cf9e614622fca52dd4b06d467ae08e47314;p=gcc.git *** empty log message *** From-SVN: r710 --- 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 +#include #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) @@ -125,6 +229,30 @@ half_pic_encode (decl) #endif } + +/* 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. */ @@ -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 */ diff --git a/gcc/halfpic.h b/gcc/halfpic.h index 0b8a61c76d8..b972ff9d17d 100644 --- a/gcc/halfpic.h +++ b/gcc/halfpic.h @@ -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)