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