OSDN Git Service

Use ## for comment.
[pf3gnuchains/gcc-fork.git] / gcc / halfpic.c
1 /* OSF/rose half-pic support functions.
2    Copyright (C) 1992, 1997, 1998, 1999 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 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 "system.h"
36 #include "tree.h"
37 #include "rtl.h"
38 #include "expr.h"
39 #include "output.h"
40 #include "obstack.h"
41 #include "halfpic.h"
42
43 #define obstack_chunk_alloc xmalloc
44 #define obstack_chunk_free free
45
46 int flag_half_pic               = 0;    /* Global half-pic flag.  */
47 int half_pic_number_ptrs        = 0;    /* # distinct pointers found */
48 int half_pic_number_refs        = 0;    /* # half-pic references */
49 int (*ptr_half_pic_address_p) PARAMS ((rtx)) = half_pic_address_p;
50
51 /* Obstack to hold generated pic names.  */
52 static struct obstack half_pic_obstack;
53
54 /* List of pointers created to pic references.  */
55
56 struct all_refs {
57   struct all_refs *hash_next;   /* next name in hash chain */
58   struct all_refs *next;        /* next name created */
59   int              external_p;  /* name is an external reference */
60   int              pointer_p;   /* pointer created.  */
61   const char      *ref_name;    /* reference name to ptr to real_name */
62   int              ref_len;     /* reference name length */
63   const char      *real_name;   /* real function/data name */
64   int              real_len;    /* strlen (real_name) */
65 };
66
67 static struct all_refs *half_pic_names;
68
69 static const char *half_pic_prefix;
70 static int   half_pic_prefix_len;
71
72 \f
73 /* Return the hash bucket of a name or NULL.  The hash chain is
74    organized as a self reorganizing circularly linked chain.  It is
75    assumed that any name passed to use will never be reallocated.  For
76    names in SYMBOL_REF's this is true, because the names are allocated
77    on the permanent obstack.  */
78
79 #ifndef MAX_HASH_TABLE
80 #define MAX_HASH_TABLE 1009
81 #endif
82
83 #define HASHBITS 30
84
85 static struct all_refs *half_pic_hash PARAMS ((const char *, int, int));
86
87 static struct all_refs *
88 half_pic_hash (name, len, create_p)
89      const 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   const 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 = (const 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           assemble_aligned_integer (POINTER_SIZE / BITS_PER_UNIT,
191                                     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       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      const 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 /* Mark that an object is explicitly external.  */
272
273 void
274 half_pic_external (name)
275      const char *name;
276 {
277   struct all_refs *ptr;
278
279   if (!flag_half_pic)
280     return;
281
282   ptr = half_pic_hash (name, 0, TRUE);
283   if (!ptr)
284     return;
285
286   ptr->external_p = TRUE;
287
288 #ifdef HALF_PIC_DEBUG
289   if (HALF_PIC_DEBUG)
290     fprintf (stderr, "\n========== Half_pic_external %s\n", name);
291 #endif
292 }
293
294 \f
295 /* Return whether an address is half-pic.  */
296
297 int
298 half_pic_address_p (addr)
299      rtx addr;
300 {
301   const char *name;
302   int len;
303   struct all_refs *ptr;
304
305   if (!flag_half_pic)
306     return FALSE;
307
308   switch (GET_CODE (addr))
309     {
310     default:
311       break;
312
313     case CONST:
314       {
315         rtx offset = const0_rtx;
316         addr = eliminate_constant_term (XEXP (addr, 0), &offset);
317         if (GET_CODE (addr) != SYMBOL_REF)
318           return FALSE;
319       }
320       /* fall through */
321
322     case SYMBOL_REF:
323       name = XSTR (addr, 0);
324
325 #ifdef HALF_PIC_DEBUG
326       if (HALF_PIC_DEBUG)
327         fprintf (stderr, "\n========== Half_pic_address_p %s\n", name);
328 #endif
329
330       /* If this is a label, it will have a '*' in front of it.  */
331       if (name[0] == '*')
332         return FALSE;
333
334       /* If this is a reference to the actual half-pic pointer, it
335          is obviously not half-pic.  */
336
337       len = strlen (name);
338       if (len > half_pic_prefix_len
339           && half_pic_prefix[0] == name[0]
340           && !strncmp (name, half_pic_prefix, half_pic_prefix_len))
341         return FALSE;
342
343       ptr = half_pic_hash (name, len, FALSE);
344       if (ptr == (struct all_refs *) 0)
345         return FALSE;
346
347       if (ptr->external_p)
348         {
349 #ifdef HALF_PIC_DEBUG
350           if (HALF_PIC_DEBUG)
351             fprintf (stderr, "%s is half-pic\n", name);
352 #endif
353           return TRUE;
354         }
355     }
356
357   return FALSE;
358 }
359
360 \f
361 /* Return the name of the pointer to the PIC function, allocating
362    it if need be.  */
363
364 struct rtx_def *
365 half_pic_ptr (operand)
366      rtx operand;
367 {
368   const char *name;
369   struct all_refs *p;
370   int len;
371
372   if (GET_CODE (operand) != SYMBOL_REF)
373     return operand;
374
375   name = XSTR (operand, 0);
376   len = strlen (name);
377   p = half_pic_hash (name, len, FALSE);
378   if (p == (struct all_refs *) 0 || !p->external_p)
379     return operand;
380
381   if (!p->pointer_p)
382     {                           /* first time, create pointer */
383       obstack_grow (&half_pic_obstack, half_pic_prefix, half_pic_prefix_len);
384       obstack_grow (&half_pic_obstack, name, len+1);
385
386       p->next      = half_pic_names;
387       p->ref_name  = (char *) obstack_finish (&half_pic_obstack);
388       p->ref_len   = len + half_pic_prefix_len;
389       p->pointer_p = TRUE;
390
391       half_pic_names = p;
392       half_pic_number_ptrs++;
393     }
394
395   half_pic_number_refs++;
396   return gen_rtx_SYMBOL_REF (Pmode, p->ref_name);
397 }
398
399 #endif /* HALF_PIC_INIT */