source: trunk/third/gcc/halfpic.c @ 8834

Revision 8834, 8.9 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r8833, which included commits to RCS files with non-trunk default branches.
Line 
1/* OSF/rose half-pic support functions.
2   Copyright (C) 1992 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING.  If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.  */
20
21/* The OSF/rose half-pic model assumes that the non-library code does
22   not need to have full PIC (position independent code), but rather,
23   that pointers to external references are put into the data section
24   and dereferenced as normal pointers.  References to static data does
25   not need to be PIC-ized.
26
27   Another optimization is to have the compiler know what symbols are
28   in the shared libraries, and to only lay down the pointers to
29   things which in the library proper.  */
30
31#include "config.h"
32
33#ifdef HALF_PIC_INIT
34
35#include "tree.h"
36#include "rtl.h"
37#include <stdio.h>
38#include "obstack.h"
39
40#define obstack_chunk_alloc xmalloc
41#define obstack_chunk_free free
42
43extern char *xmalloc ();
44extern void  free ();
45extern rtx eliminate_constant_term ();
46extern void assemble_name ();
47extern void output_addr_const ();
48
49int flag_half_pic               = 0;    /* Global half-pic flag.  */
50int half_pic_number_ptrs        = 0;    /* # distinct pointers found */
51int half_pic_number_refs        = 0;    /* # half-pic references */
52int (*ptr_half_pic_address_p)() = half_pic_address_p;
53
54/* Obstack to hold generated pic names.  */
55static struct obstack half_pic_obstack;
56
57/* List of pointers created to pic references.  */
58
59struct all_refs {
60  struct all_refs *hash_next;   /* next name in hash chain */
61  struct all_refs *next;        /* next name created */
62  int              external_p;  /* name is an external reference */
63  int              pointer_p;   /* pointer created.  */
64  char            *ref_name;    /* reference name to ptr to real_name */
65  int              ref_len;     /* reference name length */
66  char            *real_name;   /* real function/data name */
67  int              real_len;    /* strlen (real_name) */
68};
69
70static struct all_refs *half_pic_names;
71
72static char *half_pic_prefix;
73static int   half_pic_prefix_len;
74
75
76/* Return the hash bucket of a name or NULL.  The hash chain is
77   organized as a self reorganizing circularly linked chain.  It is
78   assumed that any name passed to use will never be reallocated.  For
79   names in SYMBOL_REF's this is true, because the names are allocated
80   on the permanent obstack.  */
81
82#ifndef MAX_HASH_TABLE
83#define MAX_HASH_TABLE 1009
84#endif
85
86#define HASHBITS 30
87
88static struct all_refs *
89half_pic_hash (name, len, create_p)
90     char *name;                /* name to hash */
91     int len;                   /* length of the name (or 0 to call strlen) */
92     int create_p;              /* != 0 to create new hash bucket if new */
93{
94  static struct all_refs *hash_table[MAX_HASH_TABLE];
95  static struct all_refs  zero_all_refs;
96
97  unsigned char *uname;
98  int hash;
99  int i;
100  int ch;
101  struct all_refs *first;
102  struct all_refs *ptr;
103
104  if (len == 0)
105    len = strlen (name);
106
107  /* Compute hash code */
108  uname = (unsigned char *)name;
109  ch = uname[0];
110  hash = len * 613 + ch;
111  for (i = 1; i < len; i += 2)
112    hash = (hash * 613) + uname[i];
113
114  hash &= (1 << HASHBITS) - 1;
115  hash %= MAX_HASH_TABLE;
116
117  /* See if the name is in the hash table.  */
118  ptr = first = hash_table[hash];
119  if (ptr)
120    {
121      do
122        {
123          if (len == ptr->real_len
124              && ch == *(ptr->real_name)
125              && !strcmp (name, ptr->real_name))
126            {
127              hash_table[hash] = ptr;
128              return ptr;
129            }
130
131          ptr = ptr->hash_next;
132        }
133      while (ptr != first);
134    }
135
136  /* name not in hash table.  */
137  if (!create_p)
138    return (struct all_refs *)0;
139
140  ptr = (struct all_refs *) obstack_alloc (&half_pic_obstack, sizeof (struct all_refs));
141  *ptr = zero_all_refs;
142
143  ptr->real_name = name;
144  ptr->real_len  = len;
145
146  /* Update circular links.  */
147  if (first == (struct all_refs *)0)
148    ptr->hash_next = ptr;
149
150  else
151    {
152      ptr->hash_next = first->hash_next;
153      first->hash_next = ptr;
154    }
155
156  hash_table[hash] = ptr;
157  return ptr;
158}
159
160
161/* Do any half-pic initializations.  */
162
163void
164half_pic_init ()
165{
166  flag_half_pic = TRUE;
167  half_pic_prefix = HALF_PIC_PREFIX;
168  half_pic_prefix_len = strlen (half_pic_prefix);
169  obstack_init (&half_pic_obstack);
170}
171
172
173/* Write out all pointers to pic references.  */
174
175void
176half_pic_finish (stream)
177     FILE *stream;
178{
179  struct all_refs *p = half_pic_names;
180
181  if (!p)
182    return;
183
184  data_section ();
185  for (; p != 0; p = p->next)
186    {
187      /* Emit the pointer if used.  */
188      if (p->pointer_p)
189        {
190          ASM_OUTPUT_LABEL (stream, p->ref_name);
191          ASM_OUTPUT_INT (stream, gen_rtx (SYMBOL_REF, Pmode, p->real_name));
192        }
193    }
194}
195
196
197/* Encode in a declaration whether or not it is half-pic.  */
198
199void
200half_pic_encode (decl)
201     tree decl;
202{
203  enum tree_code code = TREE_CODE (decl);
204  tree asm_name;
205  struct all_refs *ptr;
206
207  if (!flag_half_pic)
208    return;
209
210  if (code != VAR_DECL && code != FUNCTION_DECL)
211    return;
212
213  asm_name = DECL_ASSEMBLER_NAME (decl);
214
215  if (!asm_name)
216    return;
217
218#ifdef HALF_PIC_DEBUG
219  if (HALF_PIC_DEBUG)
220    {
221      if (HALF_PIC_DEBUG)
222        fprintf (stderr, "\n========== Half_pic_encode %.*s\n",
223                 IDENTIFIER_LENGTH (asm_name),
224                 IDENTIFIER_POINTER (asm_name));
225      debug_tree (decl);
226    }
227#endif
228
229  /* If this is not an external reference, it can't be half-pic.  */
230  if (!DECL_EXTERNAL (decl) && (code != VAR_DECL || !TREE_PUBLIC (decl)))
231    return;
232
233  ptr = half_pic_hash (IDENTIFIER_POINTER (asm_name),
234                       IDENTIFIER_LENGTH (asm_name),
235                       TRUE);
236
237  ptr->external_p = TRUE;
238
239#ifdef HALF_PIC_DEBUG
240  if (HALF_PIC_DEBUG)
241    fprintf (stderr, "\n%.*s is half-pic\n",
242             IDENTIFIER_LENGTH (asm_name),
243             IDENTIFIER_POINTER (asm_name));
244#endif
245}
246
247
248/* Mark that an object is now local, and no longer needs half-pic.  */
249
250void
251half_pic_declare (name)
252     char *name;
253{
254  struct all_refs *ptr;
255
256  if (!flag_half_pic)
257    return;
258
259  ptr = half_pic_hash (name, 0, FALSE);
260  if (!ptr)
261    return;
262
263  ptr->external_p = FALSE;
264
265#ifdef HALF_PIC_DEBUG
266  if (HALF_PIC_DEBUG)
267    fprintf (stderr, "\n========== Half_pic_declare %s\n", name);
268#endif
269}
270
271
272/* Mark that an object is explicitly external.  */
273
274void
275half_pic_external (name)
276     char *name;
277{
278  struct all_refs *ptr;
279
280  if (!flag_half_pic)
281    return;
282
283  ptr = half_pic_hash (name, 0, TRUE);
284  if (!ptr)
285    return;
286
287  ptr->external_p = TRUE;
288
289#ifdef HALF_PIC_DEBUG
290  if (HALF_PIC_DEBUG)
291    fprintf (stderr, "\n========== Half_pic_external %s\n", name);
292#endif
293}
294
295
296/* Return whether an address is half-pic.  */
297
298int
299half_pic_address_p (addr)
300     rtx addr;
301{
302  char *name;
303  int len;
304  struct all_refs *ptr;
305
306  if (!flag_half_pic)
307    return FALSE;
308
309  switch (GET_CODE (addr))
310    {
311    default:
312      break;
313
314    case CONST:
315      {
316        rtx offset = const0_rtx;
317        addr = eliminate_constant_term (XEXP (addr, 0), &offset);
318        if (GET_CODE (addr) != SYMBOL_REF)
319          return FALSE;
320      }
321      /* fall through */
322
323    case SYMBOL_REF:
324      name = XSTR (addr, 0);
325
326#ifdef HALF_PIC_DEBUG
327      if (HALF_PIC_DEBUG)
328        fprintf (stderr, "\n========== Half_pic_address_p %s\n", name);
329#endif
330
331      /* If this is a label, it will have a '*' in front of it.  */
332      if (name[0] == '*')
333        return FALSE;
334
335      /* If this is a reference to the actual half-pic pointer, it
336         is obviously not half-pic.  */
337
338      len = strlen (name);
339      if (len > half_pic_prefix_len
340          && half_pic_prefix[0] == name[0]
341          && !strncmp (name, half_pic_prefix, half_pic_prefix_len))
342        return FALSE;
343
344      ptr = half_pic_hash (name, len, FALSE);
345      if (ptr == (struct all_refs *)0)
346        return FALSE;
347
348      if (ptr->external_p)
349        {
350#ifdef HALF_PIC_DEBUG
351          if (HALF_PIC_DEBUG)
352            fprintf (stderr, "%s is half-pic\n", name);
353#endif
354          return TRUE;
355        }
356    }
357
358  return FALSE;
359}
360
361
362/* Return the name of the pointer to the PIC function, allocating
363   it if need be.  */
364
365struct rtx_def *
366half_pic_ptr (operand)
367     rtx operand;
368{
369  char *name;
370  struct all_refs *p;
371  int len;
372
373  if (GET_CODE (operand) != SYMBOL_REF)
374    return operand;
375
376  name = XSTR (operand, 0);
377  len = strlen (name);
378  p = half_pic_hash (name, len, FALSE);
379  if (p == (struct all_refs *)0 || !p->external_p)
380    return operand;
381
382  if (!p->pointer_p)
383    {                           /* first time, create pointer */
384      obstack_grow (&half_pic_obstack, half_pic_prefix, half_pic_prefix_len);
385      obstack_grow (&half_pic_obstack, name, len+1);
386
387      p->next      = half_pic_names;
388      p->ref_name  = (char *) obstack_finish (&half_pic_obstack);
389      p->ref_len   = len + half_pic_prefix_len;
390      p->pointer_p = TRUE;
391
392      half_pic_names = p;
393      half_pic_number_ptrs++;
394    }
395
396  half_pic_number_refs++;
397  return gen_rtx (SYMBOL_REF, Pmode, p->ref_name);
398}
399
400#endif /* HALF_PIC_INIT */
Note: See TracBrowser for help on using the repository browser.