]> gcc.gnu.org Git - gcc.git/blob - gcc/halfpic.c
*** empty log message ***
[gcc.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 <string.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; /* Global half-pic flag. */
50 int half_pic_number_ptrs; /* # distinct pointers found */
51 int half_pic_number_refs; /* # half-pic references */
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 /* If this is not an external reference, it can't be half-pic. */
213 if (!TREE_EXTERNAL (decl))
214 return;
215
216 asm_name = DECL_ASSEMBLER_NAME (decl);
217 if (!asm_name)
218 return;
219
220 ptr = half_pic_hash (IDENTIFIER_POINTER (asm_name),
221 IDENTIFIER_LENGTH (asm_name),
222 TRUE);
223
224 ptr->external_p = TRUE;
225
226 #ifdef HALF_PIC_DEBUG
227 if (HALF_PIC_DEBUG)
228 fprintf (stderr, "\n========== Half_pic_encode %.*s\n",
229 IDENTIFIER_LENGTH (asm_name),
230 IDENTIFIER_POINTER (asm_name));
231 #endif
232 }
233
234 \f
235 /* Mark that an object is now local, and no longer needs half-pic. */
236
237 void
238 half_pic_declare (name)
239 char *name;
240 {
241 struct all_refs *ptr;
242
243 if (!flag_half_pic)
244 return;
245
246 ptr = half_pic_hash (name, 0, FALSE);
247 if (!ptr)
248 return;
249
250 ptr->external_p = FALSE;
251
252 #ifdef HALF_PIC_DEBUG
253 if (HALF_PIC_DEBUG)
254 fprintf (stderr, "\n========== Half_pic_declare %s\n", name);
255 #endif
256 }
257
258 \f
259 /* Return whether an address is half-pic. */
260
261 int
262 half_pic_address_p (addr)
263 rtx addr;
264 {
265 char *name;
266 int len;
267 struct all_refs *ptr;
268
269 if (!flag_half_pic)
270 return FALSE;
271
272 switch (GET_CODE (addr))
273 {
274 default:
275 break;
276
277 case CONST:
278 {
279 rtx offset = const0_rtx;
280 addr = eliminate_constant_term (addr, &offset);
281 if (GET_CODE (addr) != SYMBOL_REF)
282 return FALSE;
283 }
284 /* fall through */
285
286 case SYMBOL_REF:
287 name = XSTR (addr, 0);
288
289 #ifdef HALF_PIC_DEBUG
290 if (HALF_PIC_DEBUG)
291 fprintf (stderr, "\n========== Half_pic_address_p %s\n", name);
292 #endif
293
294 /* If this is a label, it will have a '*' in front of it. */
295 if (name[0] == '*')
296 return FALSE;
297
298 /* If this is a reference to the actual half-pic pointer, it
299 is obviously not half-pic. */
300
301 len = strlen (name);
302 if (len > half_pic_prefix_len
303 && half_pic_prefix[0] == name[0]
304 && !strncmp (name, half_pic_prefix, half_pic_prefix_len))
305 return FALSE;
306
307 ptr = half_pic_hash (name, len, FALSE);
308 if (ptr == (struct all_refs *)0)
309 return FALSE;
310
311 if (ptr->external_p)
312 {
313 #ifdef HALF_PIC_DEBUG
314 if (HALF_PIC_DEBUG)
315 fprintf (stderr, "%s is half-pic\n", name);
316 #endif
317 return TRUE;
318 }
319 }
320
321 return FALSE;
322 }
323
324 \f
325 /* Return the name of the pointer to the PIC function, allocating
326 it if need be. */
327
328 struct rtx_def *
329 half_pic_ptr (operand)
330 rtx operand;
331 {
332 char *name;
333 struct all_refs *p;
334 int len;
335
336 if (GET_CODE (operand) != SYMBOL_REF)
337 return operand;
338
339 name = XSTR (operand, 0);
340 len = strlen (name);
341 p = half_pic_hash (name, len, FALSE);
342 if (p == (struct all_refs *)0 || !p->external_p)
343 return operand;
344
345 if (!p->pointer_p)
346 { /* first time, create pointer */
347 obstack_grow (&half_pic_obstack, half_pic_prefix, half_pic_prefix_len);
348 obstack_grow (&half_pic_obstack, name, len+1);
349
350 p->next = half_pic_names;
351 p->ref_name = (char *) obstack_finish (&half_pic_obstack);
352 p->ref_len = len + half_pic_prefix_len;
353 p->pointer_p = TRUE;
354
355 half_pic_names = p;
356 half_pic_number_ptrs++;
357 }
358
359 half_pic_number_refs++;
360 return gen_rtx (SYMBOL_REF, Pmode, p->ref_name);
361 }
362
363 #endif /* HALF_PIC_INIT */
This page took 0.05007 seconds and 5 git commands to generate.