|
|
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.