|
|
1.1 ! root 1: /* Code to maintain a C++ template repository. ! 2: Copyright (C) 1995 Free Software Foundation, Inc. ! 3: Contributed by Jason Merrill ([email protected]) ! 4: ! 5: This file is part of GNU CC. ! 6: ! 7: GNU CC is free software; you can redistribute it and/or modify ! 8: it under the terms of the GNU General Public License as published by ! 9: the Free Software Foundation; either version 2, or (at your option) ! 10: any later version. ! 11: ! 12: GNU CC is distributed in the hope that it will be useful, ! 13: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 15: GNU General Public License for more details. ! 16: ! 17: You should have received a copy of the GNU General Public License ! 18: along with GNU CC; see the file COPYING. If not, write to ! 19: the Free Software Foundation, 59 Temple Place - Suite 330, ! 20: Boston, MA 02111-1307, USA. */ ! 21: ! 22: /* My strategy here is as follows: ! 23: ! 24: Everything should be emitted in a translation unit where it is used. ! 25: The results of the automatic process should be easily reproducible with ! 26: explicit code. */ ! 27: ! 28: #include <stdio.h> ! 29: #include "config.h" ! 30: #include "tree.h" ! 31: #include "cp-tree.h" ! 32: #include "input.h" ! 33: #include "obstack.h" ! 34: ! 35: extern char * rindex (); ! 36: extern char * getenv (); ! 37: extern char * getpwd (); ! 38: ! 39: static tree pending_repo; ! 40: static tree original_repo; ! 41: static char *repo_name; ! 42: static FILE *repo_file; ! 43: ! 44: extern int flag_use_repository; ! 45: extern int errorcount, sorrycount; ! 46: extern struct obstack temporary_obstack; ! 47: extern struct obstack permanent_obstack; ! 48: ! 49: #define IDENTIFIER_REPO_USED(NODE) (TREE_LANG_FLAG_3 (NODE)) ! 50: #define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE)) ! 51: ! 52: /* Record the flags used to compile this translation unit. */ ! 53: ! 54: void ! 55: repo_compile_flags (argc, argv) ! 56: int argc; ! 57: char **argv; ! 58: { ! 59: } ! 60: ! 61: /* If this template has not been seen before, add a note to the repository ! 62: saying where the declaration was. This may be used to find the ! 63: definition at link time. */ ! 64: ! 65: void ! 66: repo_template_declared (t) ! 67: tree t; ! 68: {} ! 69: ! 70: /* Note where the definition of a template lives so that instantiations can ! 71: be generated later. */ ! 72: ! 73: void ! 74: repo_template_defined (t) ! 75: tree t; ! 76: {} ! 77: ! 78: /* Note where the definition of a class lives to that template ! 79: instantiations can use it. */ ! 80: ! 81: void ! 82: repo_class_defined (t) ! 83: tree t; ! 84: {} ! 85: ! 86: tree ! 87: repo_get_id (t) ! 88: tree t; ! 89: { ! 90: if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') ! 91: { ! 92: t = TYPE_BINFO_VTABLE (t); ! 93: if (t == NULL_TREE) ! 94: return t; ! 95: } ! 96: return DECL_ASSEMBLER_NAME (t); ! 97: } ! 98: ! 99: /* Note that a template has been used. If we can see the definition, offer ! 100: to emit it. */ ! 101: ! 102: void ! 103: repo_template_used (t) ! 104: tree t; ! 105: { ! 106: tree id; ! 107: ! 108: if (! flag_use_repository) ! 109: return; ! 110: ! 111: id = repo_get_id (t); ! 112: if (id == NULL_TREE) ! 113: return; ! 114: ! 115: if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') ! 116: { ! 117: if (IDENTIFIER_REPO_CHOSEN (id)) ! 118: mark_class_instantiated (t, 0); ! 119: } ! 120: else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd') ! 121: { ! 122: if (IDENTIFIER_REPO_CHOSEN (id)) ! 123: mark_function_instantiated (t, 0); ! 124: } ! 125: else ! 126: my_friendly_abort (1); ! 127: ! 128: if (! IDENTIFIER_REPO_USED (id)) ! 129: { ! 130: IDENTIFIER_REPO_USED (id) = 1; ! 131: pending_repo = perm_tree_cons (NULL_TREE, id, pending_repo); ! 132: } ! 133: } ! 134: ! 135: /* Note that the vtable for a class has been used, and offer to emit it. */ ! 136: ! 137: void ! 138: repo_vtable_used (t) ! 139: tree t; ! 140: { ! 141: if (! flag_use_repository) ! 142: return; ! 143: ! 144: pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo); ! 145: } ! 146: ! 147: /* Note that an inline with external linkage has been used, and offer to ! 148: emit it. */ ! 149: ! 150: void ! 151: repo_inline_used (fn) ! 152: tree fn; ! 153: { ! 154: if (! flag_use_repository) ! 155: return; ! 156: ! 157: /* Member functions of polymorphic classes go with their vtables. */ ! 158: if (DECL_FUNCTION_MEMBER_P (fn) && TYPE_VIRTUAL_P (DECL_CLASS_CONTEXT (fn))) ! 159: { ! 160: repo_vtable_used (DECL_CLASS_CONTEXT (fn)); ! 161: return; ! 162: } ! 163: ! 164: pending_repo = perm_tree_cons (NULL_TREE, fn, pending_repo); ! 165: } ! 166: ! 167: /* Note that a particular typeinfo node has been used, and offer to ! 168: emit it. */ ! 169: ! 170: void ! 171: repo_tinfo_used (ti) ! 172: tree ti; ! 173: { ! 174: } ! 175: ! 176: void ! 177: repo_template_instantiated (t, extern_p) ! 178: tree t; ! 179: int extern_p; ! 180: { ! 181: if (! extern_p) ! 182: { ! 183: tree id = repo_get_id (t); ! 184: if (id) ! 185: IDENTIFIER_REPO_CHOSEN (id) = 1; ! 186: } ! 187: } ! 188: ! 189: static char * ! 190: save_string (s, len) ! 191: char *s; ! 192: int len; ! 193: { ! 194: return obstack_copy0 (&temporary_obstack, s, len); ! 195: } ! 196: ! 197: static char * ! 198: get_base_filename (filename) ! 199: char *filename; ! 200: { ! 201: char *p = getenv ("COLLECT_GCC_OPTIONS"); ! 202: char *output = 0; ! 203: int compiling = 0; ! 204: ! 205: if (p) ! 206: while (*p) ! 207: { ! 208: char *q = p; ! 209: while (*q && *q != ' ') q++; ! 210: if (*p == '-' && p[1] == 'o') ! 211: { ! 212: p += 2; ! 213: if (p == q) ! 214: { ! 215: p++; q++; ! 216: if (*q) ! 217: while (*q && *q != ' ') q++; ! 218: } ! 219: ! 220: output = save_string (p, q - p); ! 221: } ! 222: else if (*p == '-' && p[1] == 'c') ! 223: compiling = 1; ! 224: if (*q) q++; ! 225: p = q; ! 226: } ! 227: ! 228: if (compiling && output) ! 229: return output; ! 230: ! 231: if (p && ! compiling) ! 232: { ! 233: warning ("-frepo must be used with -c"); ! 234: flag_use_repository = 0; ! 235: return NULL; ! 236: } ! 237: ! 238: p = rindex (filename, '/'); ! 239: if (p) ! 240: return p+1; ! 241: else ! 242: return filename; ! 243: } ! 244: ! 245: static void ! 246: open_repo_file (filename) ! 247: char *filename; ! 248: { ! 249: register char *p, *q; ! 250: char *s = get_base_filename (filename); ! 251: ! 252: if (s == NULL) ! 253: return; ! 254: ! 255: p = rindex (s, '/'); ! 256: if (! p) ! 257: p = s; ! 258: p = rindex (p, '.'); ! 259: if (! p) ! 260: p = s + strlen (s); ! 261: ! 262: obstack_grow (&permanent_obstack, s, p - s); ! 263: repo_name = obstack_copy0 (&permanent_obstack, ".rpo", 4); ! 264: ! 265: repo_file = fopen (repo_name, "r"); ! 266: } ! 267: ! 268: static char * ! 269: afgets (stream) ! 270: FILE *stream; ! 271: { ! 272: int c; ! 273: while ((c = getc (stream)) != EOF && c != '\n') ! 274: obstack_1grow (&temporary_obstack, c); ! 275: if (obstack_object_size (&temporary_obstack) == 0) ! 276: return NULL; ! 277: obstack_1grow (&temporary_obstack, '\0'); ! 278: return obstack_finish (&temporary_obstack); ! 279: } ! 280: ! 281: void ! 282: init_repo (filename) ! 283: char *filename; ! 284: { ! 285: char *buf; ! 286: ! 287: if (! flag_use_repository) ! 288: return; ! 289: ! 290: open_repo_file (filename); ! 291: ! 292: if (repo_file == 0) ! 293: return; ! 294: ! 295: while (buf = afgets (repo_file)) ! 296: { ! 297: switch (buf[0]) ! 298: { ! 299: case 'A': ! 300: case 'D': ! 301: case 'M': ! 302: break; ! 303: case 'C': ! 304: case 'O': ! 305: { ! 306: tree id = get_identifier (buf + 2); ! 307: tree orig; ! 308: ! 309: if (buf[0] == 'C') ! 310: { ! 311: IDENTIFIER_REPO_CHOSEN (id) = 1; ! 312: orig = integer_one_node; ! 313: } ! 314: else ! 315: orig = NULL_TREE; ! 316: ! 317: original_repo = perm_tree_cons (orig, id, original_repo); ! 318: } ! 319: break; ! 320: default: ! 321: error ("mysterious repository information in %s", repo_name); ! 322: } ! 323: obstack_free (&temporary_obstack, buf); ! 324: } ! 325: } ! 326: ! 327: static void ! 328: reopen_repo_file_for_write () ! 329: { ! 330: if (repo_file) ! 331: fclose (repo_file); ! 332: repo_file = fopen (repo_name, "w"); ! 333: ! 334: if (repo_file == 0) ! 335: { ! 336: error ("can't create repository information file `%s'", repo_name); ! 337: flag_use_repository = 0; ! 338: } ! 339: } ! 340: ! 341: /* Emit any pending repos. */ ! 342: ! 343: void ! 344: finish_repo () ! 345: { ! 346: tree t; ! 347: char *p; ! 348: int repo_changed = 0; ! 349: ! 350: if (! flag_use_repository) ! 351: return; ! 352: ! 353: /* Do we have to write out a new info file? */ ! 354: ! 355: /* Are there any old templates that aren't used any longer or that are ! 356: newly chosen? */ ! 357: ! 358: for (t = original_repo; t; t = TREE_CHAIN (t)) ! 359: { ! 360: if (! IDENTIFIER_REPO_USED (TREE_VALUE (t)) ! 361: || (! TREE_PURPOSE (t) && IDENTIFIER_REPO_CHOSEN (TREE_VALUE (t)))) ! 362: { ! 363: repo_changed = 1; ! 364: break; ! 365: } ! 366: IDENTIFIER_REPO_USED (TREE_VALUE (t)) = 0; ! 367: } ! 368: ! 369: /* Are there any templates that are newly used? */ ! 370: ! 371: if (! repo_changed) ! 372: for (t = pending_repo; t; t = TREE_CHAIN (t)) ! 373: { ! 374: if (IDENTIFIER_REPO_USED (TREE_VALUE (t))) ! 375: { ! 376: repo_changed = 1; ! 377: break; ! 378: } ! 379: } ! 380: ! 381: if (! repo_changed || errorcount || sorrycount) ! 382: goto out; ! 383: ! 384: reopen_repo_file_for_write (); ! 385: ! 386: if (repo_file == 0) ! 387: goto out; ! 388: ! 389: fprintf (repo_file, "M %s\n", main_input_filename); ! 390: ! 391: p = getpwd (); ! 392: fprintf (repo_file, "D %s\n", p); ! 393: ! 394: p = getenv ("COLLECT_GCC_OPTIONS"); ! 395: if (p != 0) ! 396: fprintf (repo_file, "A %s\n", p); ! 397: ! 398: for (t = pending_repo; t; t = TREE_CHAIN (t)) ! 399: { ! 400: tree val = TREE_VALUE (t); ! 401: char type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O'; ! 402: ! 403: fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (val)); ! 404: } ! 405: ! 406: out: ! 407: if (repo_file) ! 408: fclose (repo_file); ! 409: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.