|
|
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 <string.h>
! 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:
49: int flag_half_pic; /* Global half-pic flag. */
1.1.1.3 ! root 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:
! 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: }
1.1 root 158:
159:
160: /* Do any half-pic initializations. */
161:
162: void
163: half_pic_init ()
164: {
165: flag_half_pic = TRUE;
1.1.1.3 ! root 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: }
1.1 root 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: {
1.1.1.3 ! root 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:
! 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);
1.1 root 255: #endif
256: }
257:
258:
259: /* Return whether an address is half-pic. */
260:
261: int
262: half_pic_address_p (addr)
263: rtx addr;
264: {
265: char *name;
1.1.1.3 ! root 266: int len;
! 267: struct all_refs *ptr;
! 268:
! 269: if (!flag_half_pic)
! 270: return FALSE;
1.1 root 271:
272: switch (GET_CODE (addr))
273: {
1.1.1.3 ! root 274: default:
! 275: break;
! 276:
1.1 root 277: case CONST:
1.1.1.2 root 278: {
279: rtx offset = const0_rtx;
280: addr = eliminate_constant_term (addr, &offset);
281: if (GET_CODE (addr) != SYMBOL_REF)
282: return FALSE;
283: }
1.1 root 284: /* fall through */
285:
286: case SYMBOL_REF:
287: name = XSTR (addr, 0);
288:
1.1.1.3 ! root 289: #ifdef HALF_PIC_DEBUG
! 290: if (HALF_PIC_DEBUG)
! 291: fprintf (stderr, "\n========== Half_pic_address_p %s\n", name);
! 292: #endif
! 293:
1.1 root 294: /* If this is a label, it will have a '*' in front of it. */
295: if (name[0] == '*')
296: return FALSE;
1.1.1.3 ! root 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: }
1.1 root 319: }
320:
321: return FALSE;
322: }
323:
1.1.1.3 ! root 324:
! 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:
1.1 root 363: #endif /* HALF_PIC_INIT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.