OSDN Git Service

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