|
|
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
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 "obstack.h"
38:
39: #define obstack_chunk_alloc xmalloc
40: #define obstack_chunk_free free
41:
42: extern char *xmalloc ();
43: extern void free ();
44: extern rtx eliminate_constant_term ();
45: extern void assemble_name ();
46: extern void output_addr_const ();
47:
48: int flag_half_pic = 0; /* Global half-pic flag. */
49: int half_pic_number_ptrs = 0; /* # distinct pointers found */
50: int half_pic_number_refs = 0; /* # half-pic references */
51: int (*ptr_half_pic_address_p)() = half_pic_address_p;
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:
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:
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:
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:
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: asm_name = DECL_ASSEMBLER_NAME (decl);
213:
214: if (!asm_name)
215: return;
216:
217: #ifdef HALF_PIC_DEBUG
218: if (HALF_PIC_DEBUG)
219: {
220: if (HALF_PIC_DEBUG)
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:
247: /* Mark that an object is now local, and no longer needs half-pic. */
248:
249: void
250: half_pic_declare (name)
251: 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:
271: /* Mark that an object is explicitly external. */
272:
273: void
274: half_pic_external (name)
275: 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:
295: /* Return whether an address is half-pic. */
296:
297: int
298: half_pic_address_p (addr)
299: rtx addr;
300: {
301: 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:
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: 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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.