OSDN Git Service

(find_reloads_address_1, case POST_INC): Don't use
[pf3gnuchains/gcc-fork.git] / gcc / halfpic.c
1 /* OSF/rose half-pic support functions.
2    Copyright (C) 1992 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, 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
43 extern char *xmalloc ();
44 extern void  free ();
45 extern rtx eliminate_constant_term ();
46 extern void assemble_name ();
47 extern void output_addr_const ();
48
49 int flag_half_pic               = 0;    /* Global half-pic flag.  */
50 int half_pic_number_ptrs        = 0;    /* # distinct pointers found */
51 int half_pic_number_refs        = 0;    /* # half-pic references */
52 int (*ptr_half_pic_address_p)() = half_pic_address_p;
53
54 /* Obstack to hold generated pic names.  */
55 static struct obstack half_pic_obstack;
56
57 /* List of pointers created to pic references.  */
58
59 struct 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
70 static struct all_refs *half_pic_names;
71
72 static char *half_pic_prefix;
73 static int   half_pic_prefix_len;
74
75 \f
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
88 static struct all_refs *
89 half_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 \f
161 /* Do any half-pic initializations.  */
162
163 void
164 half_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 \f
173 /* Write out all pointers to pic references.  */
174
175 void
176 half_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 \f
197 /* Encode in a declaration whether or not it is half-pic.  */
198
199 void
200 half_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 \f
248 /* Mark that an object is now local, and no longer needs half-pic.  */
249
250 void
251 half_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 \f
272 /* Mark that an object is explicitly external.  */
273
274 void
275 half_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 \f
296 /* Return whether an address is half-pic.  */
297
298 int
299 half_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 \f
362 /* Return the name of the pointer to the PIC function, allocating
363    it if need be.  */
364
365 struct rtx_def *
366 half_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 */