|
|
1.1 root 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
1.1.1.7 ! root 18: the Free Software Foundation, 59 Temple Place - Suite 330,
! 19: Boston, MA 02111-1307, USA. */
1.1 root 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
1.1.1.3 root 24: and dereferenced as normal pointers. References to static data does
1.1 root 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>
1.1.1.3 root 38: #include "obstack.h"
1.1 root 39:
1.1.1.3 root 40: #define obstack_chunk_alloc xmalloc
41: #define obstack_chunk_free free
42:
43: extern char *xmalloc ();
44: extern void free ();
1.1 root 45: extern rtx eliminate_constant_term ();
1.1.1.3 root 46: extern void assemble_name ();
47: extern void output_addr_const ();
1.1 root 48:
1.1.1.5 root 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;
1.1.1.3 root 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:
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: }
1.1 root 159:
160:
161: /* Do any half-pic initializations. */
162:
163: void
164: half_pic_init ()
165: {
166: flag_half_pic = TRUE;
1.1.1.3 root 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:
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: }
1.1 root 194: }
195:
196:
197: /* Encode in a declaration whether or not it is half-pic. */
198:
199: void
200: half_pic_encode (decl)
201: tree decl;
202: {
1.1.1.3 root 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);
1.1.1.4 root 214:
1.1.1.3 root 215: if (!asm_name)
216: return;
217:
1.1.1.4 root 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:
1.1.1.3 root 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)
1.1.1.4 root 241: fprintf (stderr, "\n%.*s is half-pic\n",
1.1.1.3 root 242: IDENTIFIER_LENGTH (asm_name),
243: IDENTIFIER_POINTER (asm_name));
244: #endif
245: }
246:
247:
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);
1.1 root 268: #endif
269: }
270:
271:
1.1.1.6 root 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:
1.1 root 296: /* Return whether an address is half-pic. */
297:
298: int
299: half_pic_address_p (addr)
300: rtx addr;
301: {
302: char *name;
1.1.1.3 root 303: int len;
304: struct all_refs *ptr;
305:
306: if (!flag_half_pic)
307: return FALSE;
1.1 root 308:
309: switch (GET_CODE (addr))
310: {
1.1.1.3 root 311: default:
312: break;
313:
1.1 root 314: case CONST:
1.1.1.2 root 315: {
316: rtx offset = const0_rtx;
1.1.1.4 root 317: addr = eliminate_constant_term (XEXP (addr, 0), &offset);
1.1.1.2 root 318: if (GET_CODE (addr) != SYMBOL_REF)
319: return FALSE;
320: }
1.1 root 321: /* fall through */
322:
323: case SYMBOL_REF:
324: name = XSTR (addr, 0);
325:
1.1.1.3 root 326: #ifdef HALF_PIC_DEBUG
327: if (HALF_PIC_DEBUG)
328: fprintf (stderr, "\n========== Half_pic_address_p %s\n", name);
329: #endif
330:
1.1 root 331: /* If this is a label, it will have a '*' in front of it. */
332: if (name[0] == '*')
333: return FALSE;
1.1.1.3 root 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: }
1.1 root 356: }
357:
358: return FALSE;
359: }
360:
1.1.1.3 root 361:
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:
1.1 root 400: #endif /* HALF_PIC_INIT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.