Commit 58891cf9 by Michael Meissner

*** empty log message ***

From-SVN: r710
parent 2eef2ef1
......@@ -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 */
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment