]> gcc.gnu.org Git - gcc.git/blame - gcc/halfpic.c
(USER_LABEL_PREFIX): Define.
[gcc.git] / gcc / halfpic.c
CommitLineData
4f5a1f77
MM
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
a35311b0
RK
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
4f5a1f77
MM
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
c5b7917e 24 and dereferenced as normal pointers. References to static data does
4f5a1f77
MM
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>
0ea674bc 38#include "obstack.h"
4f5a1f77 39
0ea674bc
MM
40#define obstack_chunk_alloc xmalloc
41#define obstack_chunk_free free
42
43extern char *xmalloc ();
44extern void free ();
4f5a1f77 45extern rtx eliminate_constant_term ();
58891cf9
MM
46extern void assemble_name ();
47extern void output_addr_const ();
4f5a1f77 48
a89a7e4d
MM
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;
4f5a1f77 53
0ea674bc
MM
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 {
58891cf9 60 struct all_refs *hash_next; /* next name in hash chain */
0ea674bc 61 struct all_refs *next; /* next name created */
58891cf9
MM
62 int external_p; /* name is an external reference */
63 int pointer_p; /* pointer created. */
0ea674bc
MM
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
58891cf9
MM
72static char *half_pic_prefix;
73static 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
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)
0f41302f 138 return (struct all_refs *) 0;
58891cf9
MM
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. */
0f41302f 147 if (first == (struct all_refs *) 0)
58891cf9
MM
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
4f5a1f77
MM
160\f
161/* Do any half-pic initializations. */
162
163void
164half_pic_init ()
165{
166 flag_half_pic = TRUE;
58891cf9
MM
167 half_pic_prefix = HALF_PIC_PREFIX;
168 half_pic_prefix_len = strlen (half_pic_prefix);
0ea674bc
MM
169 obstack_init (&half_pic_obstack);
170}
171
172\f
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 {
58891cf9
MM
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 }
0ea674bc 193 }
4f5a1f77
MM
194}
195
196\f
197/* Encode in a declaration whether or not it is half-pic. */
198
199void
200half_pic_encode (decl)
201 tree decl;
202{
0ea674bc
MM
203 enum tree_code code = TREE_CODE (decl);
204 tree asm_name;
58891cf9 205 struct all_refs *ptr;
0ea674bc
MM
206
207 if (!flag_half_pic)
208 return;
209
210 if (code != VAR_DECL && code != FUNCTION_DECL)
211 return;
212
0ea674bc 213 asm_name = DECL_ASSEMBLER_NAME (decl);
44e57700 214
0ea674bc
MM
215 if (!asm_name)
216 return;
217
44e57700
RS
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. */
44fe2e80 230 if (!DECL_EXTERNAL (decl) && (code != VAR_DECL || !TREE_PUBLIC (decl)))
44e57700
RS
231 return;
232
58891cf9
MM
233 ptr = half_pic_hash (IDENTIFIER_POINTER (asm_name),
234 IDENTIFIER_LENGTH (asm_name),
235 TRUE);
236
237 ptr->external_p = TRUE;
0ea674bc
MM
238
239#ifdef HALF_PIC_DEBUG
240 if (HALF_PIC_DEBUG)
44e57700 241 fprintf (stderr, "\n%.*s is half-pic\n",
0ea674bc
MM
242 IDENTIFIER_LENGTH (asm_name),
243 IDENTIFIER_POINTER (asm_name));
4f5a1f77
MM
244#endif
245}
246
58891cf9
MM
247\f
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
40fbfbea
MM
271\f
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
4f5a1f77
MM
295\f
296/* Return whether an address is half-pic. */
297
298int
299half_pic_address_p (addr)
300 rtx addr;
301{
4f5a1f77 302 char *name;
58891cf9
MM
303 int len;
304 struct all_refs *ptr;
0ea674bc
MM
305
306 if (!flag_half_pic)
307 return FALSE;
4f5a1f77
MM
308
309 switch (GET_CODE (addr))
310 {
58891cf9
MM
311 default:
312 break;
313
4f5a1f77 314 case CONST:
671c2359
MM
315 {
316 rtx offset = const0_rtx;
44e57700 317 addr = eliminate_constant_term (XEXP (addr, 0), &offset);
671c2359
MM
318 if (GET_CODE (addr) != SYMBOL_REF)
319 return FALSE;
320 }
4f5a1f77
MM
321 /* fall through */
322
323 case SYMBOL_REF:
324 name = XSTR (addr, 0);
325
0ea674bc
MM
326#ifdef HALF_PIC_DEBUG
327 if (HALF_PIC_DEBUG)
328 fprintf (stderr, "\n========== Half_pic_address_p %s\n", name);
329#endif
330
4f5a1f77
MM
331 /* If this is a label, it will have a '*' in front of it. */
332 if (name[0] == '*')
333 return FALSE;
0ea674bc 334
58891cf9
MM
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);
0f41302f 345 if (ptr == (struct all_refs *) 0)
58891cf9
MM
346 return FALSE;
347
348 if (ptr->external_p)
0ea674bc
MM
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 }
4f5a1f77
MM
356 }
357
358 return FALSE;
359}
360
0ea674bc
MM
361\f
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;
0ea674bc 370 struct all_refs *p;
0ea674bc 371 int len;
0ea674bc
MM
372
373 if (GET_CODE (operand) != SYMBOL_REF)
374 return operand;
375
376 name = XSTR (operand, 0);
377 len = strlen (name);
58891cf9 378 p = half_pic_hash (name, len, FALSE);
0f41302f 379 if (p == (struct all_refs *) 0 || !p->external_p)
58891cf9 380 return operand;
0ea674bc 381
58891cf9
MM
382 if (!p->pointer_p)
383 { /* first time, create pointer */
384 obstack_grow (&half_pic_obstack, half_pic_prefix, half_pic_prefix_len);
3c1aa983 385 obstack_grow (&half_pic_obstack, name, len+1);
0ea674bc 386
58891cf9
MM
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;
0ea674bc 391
58891cf9 392 half_pic_names = p;
1d3fc420 393 half_pic_number_ptrs++;
58891cf9 394 }
0ea674bc 395
1d3fc420 396 half_pic_number_refs++;
58891cf9 397 return gen_rtx (SYMBOL_REF, Pmode, p->ref_name);
0ea674bc
MM
398}
399
4f5a1f77 400#endif /* HALF_PIC_INIT */
This page took 0.374981 seconds and 5 git commands to generate.