|
|
1.1 root 1: /* Garbage collection primitives for GNU C++. 1.1.1.5 root 2: Copyright (C) 1992, 1993 Free Software Foundation, Inc. 1.1 root 3: Contributed by Michael Tiemann ([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, 675 Mass Ave, Cambridge, MA 02139, USA. */ 20: 21: 22: #include "config.h" 23: #include "tree.h" 24: #include "cp-tree.h" 25: #include "flags.h" 1.1.1.2 root 26: 1.1.1.5 root 27: #undef NULL 1.1 root 28: #define NULL 0 29: 1.1.1.5 root 30: extern tree define_function (); 1.1 root 31: extern tree build_t_desc_overload (); 32: 33: /* This is the function decl for the (pseudo-builtin) __gc_protect 34: function. Args are (class *value, int index); Returns value. */ 35: tree gc_protect_fndecl; 36: 37: /* This is the function decl for the (pseudo-builtin) __gc_unprotect 38: function. Args are (int index); void return. */ 39: tree gc_unprotect_fndecl; 40: 41: /* This is the function decl for the (pseudo-builtin) __gc_push 42: function. Args are (int length); void return. */ 43: tree gc_push_fndecl; 44: 45: /* This is the function decl for the (pseudo-builtin) __gc_pop 46: function. Args are void; void return. */ 47: tree gc_pop_fndecl; 48: 49: /* Special integers that are used to represent bits in gc-safe objects. */ 50: tree gc_nonobject; 51: tree gc_visible; 52: tree gc_white; 53: tree gc_offwhite; 54: tree gc_grey; 55: tree gc_black; 1.1.1.5 root 56: 57: /* in c-common.c */ 58: extern tree combine_strings PROTO((tree)); 1.1 root 59: 60: /* Predicate that returns non-zero if TYPE needs some kind of 61: entry for the GC. Returns zero otherwise. */ 62: int 63: type_needs_gc_entry (type) 64: tree type; 65: { 66: tree ttype = type; 67: 68: if (! flag_gc || type == error_mark_node) 69: return 0; 70: 71: /* Aggregate types need gc entries if any of their members 72: need gc entries. */ 73: if (IS_AGGR_TYPE (type)) 74: { 75: tree binfos; 76: tree fields = TYPE_FIELDS (type); 77: int i; 78: 79: /* We don't care about certain pointers. Pointers 80: to virtual baseclasses are always up front. We also 81: cull out virtual function table pointers because it's 82: easy, and it simplifies the logic.*/ 83: while (fields 84: && (DECL_NAME (fields) == NULL_TREE 85: || VFIELD_NAME_P (DECL_NAME (fields)) 86: || VBASE_NAME_P (DECL_NAME (fields)) 87: || !strcmp (IDENTIFIER_POINTER (DECL_NAME (fields)), "__bits"))) 88: fields = TREE_CHAIN (fields); 89: 90: while (fields) 91: { 92: if (type_needs_gc_entry (TREE_TYPE (fields))) 93: return 1; 94: fields = TREE_CHAIN (fields); 95: } 96: 97: binfos = TYPE_BINFO_BASETYPES (type); 98: if (binfos) 99: for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--) 100: if (type_needs_gc_entry (BINFO_TYPE (TREE_VEC_ELT (binfos, i)))) 101: return 1; 102: 103: return 0; 104: } 105: 106: while (TREE_CODE (ttype) == ARRAY_TYPE 107: && TREE_CODE (TREE_TYPE (ttype)) == ARRAY_TYPE) 108: ttype = TREE_TYPE (ttype); 109: if ((TREE_CODE (ttype) == POINTER_TYPE 110: || TREE_CODE (ttype) == ARRAY_TYPE 111: || TREE_CODE (ttype) == REFERENCE_TYPE) 112: && IS_AGGR_TYPE (TREE_TYPE (ttype)) 113: && CLASSTYPE_DOSSIER (TREE_TYPE (ttype))) 114: return 1; 115: 116: return 0; 117: } 118: 119: /* Predicate that returns non-zero iff FROM is safe from the GC. 120: 121: If TO is nonzero, it means we know that FROM is being stored 122: in TO, which make make it safe. */ 123: int 124: value_safe_from_gc (to, from) 125: tree to, from; 126: { 127: /* First, return non-zero for easy cases: parameters, 128: static variables. */ 129: if (TREE_CODE (from) == PARM_DECL 130: || (TREE_CODE (from) == VAR_DECL 131: && TREE_STATIC (from))) 132: return 1; 133: 134: /* If something has its address taken, it cannot be 135: in the heap, so it doesn't need to be protected. */ 136: if (TREE_CODE (from) == ADDR_EXPR || TREE_REFERENCE_EXPR (from)) 137: return 1; 138: 139: /* If we are storing into a static variable, then what 140: we store will be safe from the gc. */ 141: if (to && TREE_CODE (to) == VAR_DECL 142: && TREE_STATIC (to)) 143: return 1; 144: 145: /* Now recurse on structure of FROM. */ 146: switch (TREE_CODE (from)) 147: { 148: case COMPONENT_REF: 149: /* These guys are special, and safe. */ 150: if (TREE_CODE (TREE_OPERAND (from, 1)) == FIELD_DECL 151: && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (from, 1))) 152: || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (from, 1))))) 153: return 1; 154: /* fall through... */ 155: case NOP_EXPR: 156: case CONVERT_EXPR: 157: case NON_LVALUE_EXPR: 158: case WITH_CLEANUP_EXPR: 159: case SAVE_EXPR: 160: case PREDECREMENT_EXPR: 161: case PREINCREMENT_EXPR: 162: case POSTDECREMENT_EXPR: 163: case POSTINCREMENT_EXPR: 164: if (value_safe_from_gc (to, TREE_OPERAND (from, 0))) 165: return 1; 166: break; 167: 168: case VAR_DECL: 169: case PARM_DECL: 170: /* We can safely pass these things as parameters to functions. */ 171: if (to == 0) 172: return 1; 173: 174: case ARRAY_REF: 175: case INDIRECT_REF: 176: case RESULT_DECL: 177: case OFFSET_REF: 178: case CALL_EXPR: 179: case METHOD_CALL_EXPR: 180: break; 181: 182: case COMPOUND_EXPR: 183: case TARGET_EXPR: 184: if (value_safe_from_gc (to, TREE_OPERAND (from, 1))) 185: return 1; 186: break; 187: 188: case COND_EXPR: 189: if (value_safe_from_gc (to, TREE_OPERAND (from, 1)) 190: && value_safe_from_gc (to, TREE_OPERAND (from, 2))) 191: return 1; 192: break; 193: 194: case PLUS_EXPR: 195: case MINUS_EXPR: 196: if ((type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 0))) 197: || value_safe_from_gc (to, TREE_OPERAND (from, 0))) 198: && (type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 1))) == 0 199: || value_safe_from_gc (to, TREE_OPERAND (from, 1)))) 200: return 1; 201: break; 202: 203: case RTL_EXPR: 204: /* Every time we build an RTL_EXPR in the front-end, we must 205: ensure that everything in it is safe from the garbage collector. 206: ??? This has only been done for `build_new'. */ 207: return 1; 208: 209: default: 1.1.1.3 root 210: my_friendly_abort (41); 1.1 root 211: } 212: 213: if (to == 0) 214: return 0; 215: 216: /* FROM wasn't safe. But other properties of TO might make it safe. */ 217: switch (TREE_CODE (to)) 218: { 219: case VAR_DECL: 220: case PARM_DECL: 221: /* We already culled out static VAR_DECLs above. */ 222: return 0; 223: 224: case COMPONENT_REF: 225: /* These guys are special, and safe. */ 226: if (TREE_CODE (TREE_OPERAND (to, 1)) == FIELD_DECL 227: && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (to, 1))) 228: || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (to, 1))))) 229: return 1; 230: /* fall through... */ 231: 232: case NOP_EXPR: 233: case NON_LVALUE_EXPR: 234: case WITH_CLEANUP_EXPR: 235: case SAVE_EXPR: 236: case PREDECREMENT_EXPR: 237: case PREINCREMENT_EXPR: 238: case POSTDECREMENT_EXPR: 239: case POSTINCREMENT_EXPR: 240: return value_safe_from_gc (TREE_OPERAND (to, 0), from); 241: 242: case COMPOUND_EXPR: 243: case TARGET_EXPR: 244: return value_safe_from_gc (TREE_OPERAND (to, 1), from); 245: 246: case COND_EXPR: 247: return (value_safe_from_gc (TREE_OPERAND (to, 1), from) 248: && value_safe_from_gc (TREE_OPERAND (to, 2), from)); 249: 250: case INDIRECT_REF: 251: case ARRAY_REF: 252: /* This used to be 0, but our current restricted model 253: allows this to be 1. We'll never get arrays this way. */ 254: return 1; 255: 256: default: 1.1.1.3 root 257: my_friendly_abort (42); 1.1 root 258: } 259: 260: /* Catch-all case is that TO/FROM is not safe. */ 261: return 0; 262: } 263: 264: /* Function to build a static GC entry for DECL. TYPE is DECL's type. 265: 266: For objects of type `class *', this is just an entry in the 267: static vector __PTR_LIST__. 268: 269: For objects of type `class[]', this requires building an entry 270: in the static vector __ARR_LIST__. 271: 272: For aggregates, this records all fields of type `class *' 273: and `class[]' in the respective lists above. */ 274: void 275: build_static_gc_entry (decl, type) 276: tree decl; 277: tree type; 278: { 279: /* Now, figure out what sort of entry to build. */ 280: if (TREE_CODE (type) == POINTER_TYPE 281: || TREE_CODE (type) == REFERENCE_TYPE) 282: assemble_gc_entry (IDENTIFIER_POINTER (DECL_NAME (decl))); 283: else if (TREE_CODE (type) == RECORD_TYPE) 284: { 285: tree ref = get_temp_name (build_reference_type (type), 1); 286: DECL_INITIAL (ref) = build1 (ADDR_EXPR, TREE_TYPE (ref), decl); 287: TREE_CONSTANT (DECL_INITIAL (ref)) = 1; 288: finish_decl (ref, DECL_INITIAL (ref), 0, 0); 289: } 290: else 291: { 292: /* Not yet implemented. 293: 294: Cons up a static variable that holds address and length info 295: and add that to ___ARR_LIST__. */ 1.1.1.3 root 296: my_friendly_abort (43); 1.1 root 297: } 298: } 299: 300: /* Protect FROM from the GC, assuming FROM is going to be 301: stored into TO. We handle three cases for TO here: 302: 303: case 1: TO is a stack variable. 304: case 2: TO is zero (which means it is a parameter). 305: case 3: TO is a return value. */ 306: 307: tree 308: protect_value_from_gc (to, from) 309: tree to, from; 310: { 311: if (to == 0) 312: { 313: tree cleanup; 314: 315: to = get_temp_regvar (TREE_TYPE (from), from); 316: 317: /* Convert from integer to list form since we'll use it twice. */ 318: DECL_GC_OFFSET (to) = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to)); 319: cleanup = build_function_call (gc_unprotect_fndecl, 320: DECL_GC_OFFSET (to)); 321: 322: if (! expand_decl_cleanup (to, cleanup)) 323: { 324: compiler_error ("cannot unprotect parameter in this scope"); 325: return error_mark_node; 326: } 327: } 328: 329: /* Should never need to protect a value that's headed for static storage. */ 330: if (TREE_STATIC (to)) 1.1.1.3 root 331: my_friendly_abort (44); 1.1 root 332: 333: switch (TREE_CODE (to)) 334: { 335: case COMPONENT_REF: 336: case INDIRECT_REF: 337: return protect_value_from_gc (TREE_OPERAND (to, 0), from); 338: 339: case VAR_DECL: 340: case PARM_DECL: 341: { 342: tree rval; 343: if (DECL_GC_OFFSET (to) == NULL_TREE) 344: { 345: /* Because of a cast or a conversion, we might stick 346: a value into a variable that would not normally 347: have a GC entry. */ 348: DECL_GC_OFFSET (to) = size_int (++current_function_obstack_index); 349: } 350: 351: if (TREE_CODE (DECL_GC_OFFSET (to)) != TREE_LIST) 352: { 353: DECL_GC_OFFSET (to) 354: = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to)); 355: } 356: 357: current_function_obstack_usage = 1; 358: rval = build_function_call (gc_protect_fndecl, 359: tree_cons (NULL_TREE, from, 360: DECL_GC_OFFSET (to))); 361: TREE_TYPE (rval) = TREE_TYPE (from); 362: return rval; 363: } 364: } 365: 366: /* If we fall through the switch, assume we lost. */ 1.1.1.3 root 367: my_friendly_abort (45); 1.1 root 368: /* NOTREACHED */ 369: return NULL_TREE; 370: } 371: 372: /* Given the expression EXP of type `class *', return the head 373: of the object pointed to by EXP. */ 374: tree 375: build_headof (exp) 376: tree exp; 377: { 378: tree type = TREE_TYPE (exp); 379: tree vptr, offset; 380: 381: if (TREE_CODE (type) != POINTER_TYPE) 382: { 383: error ("`headof' applied to non-pointer type"); 384: return error_mark_node; 385: } 386: 387: vptr = build1 (INDIRECT_REF, TYPE_POINTER_TO (vtable_entry_type), exp); 388: offset = build_component_ref (build_array_ref (vptr, integer_one_node), 389: get_identifier (VTABLE_DELTA_NAME), 390: NULL_TREE, 0); 391: return build (PLUS_EXPR, class_star_type_node, exp, 392: convert (integer_type_node, offset)); 393: } 394: 395: /* Given the expression EXP of type `class *', return the 396: type descriptor for the object pointed to by EXP. */ 397: tree 398: build_classof (exp) 399: tree exp; 400: { 401: tree type = TREE_TYPE (exp); 402: tree vptr; 403: tree t_desc_entry; 404: 405: if (TREE_CODE (type) != POINTER_TYPE) 406: { 407: error ("`classof' applied to non-pointer type"); 408: return error_mark_node; 409: } 410: 411: vptr = build1 (INDIRECT_REF, TYPE_POINTER_TO (vtable_entry_type), exp); 412: t_desc_entry = build_component_ref (build_array_ref (vptr, integer_one_node), 413: get_identifier (VTABLE_PFN_NAME), 414: NULL_TREE, 0); 415: TREE_TYPE (t_desc_entry) = TYPE_POINTER_TO (__t_desc_type_node); 416: return t_desc_entry; 417: } 418: 1.1.1.6 ! root 419: /* Return the Type_info node associated with the expression EXP. If EXP is ! 420: a reference to a polymorphic class, return the dynamic type; otherwise ! 421: return the static type of the expression. */ ! 422: tree ! 423: build_typeid (exp) ! 424: tree exp; ! 425: { ! 426: tree type; ! 427: ! 428: if (exp == error_mark_node) ! 429: return error_mark_node; ! 430: ! 431: type = TREE_TYPE (exp); ! 432: ! 433: /* if b is an instance of B, typeid(b) == typeid(B). Do this before ! 434: reference trickiness. */ ! 435: if (TREE_CODE (exp) == VAR_DECL && TREE_CODE (type) == RECORD_TYPE) ! 436: return get_typeid (type); ! 437: ! 438: /* Apply trivial conversion T -> T& for dereferenced ptrs. */ ! 439: if (TREE_CODE (type) == RECORD_TYPE) ! 440: type = build_reference_type (type); ! 441: ! 442: /* If exp is a reference to polymorphic type, get the real Type_info. */ ! 443: if (TREE_CODE (type) == REFERENCE_TYPE && TYPE_VIRTUAL_P (TREE_TYPE (type))) ! 444: { ! 445: /* build reference to Type_info from vtable. */ ! 446: ! 447: sorry ("finding Type_info for an object"); ! 448: return error_mark_node; ! 449: } ! 450: ! 451: /* otherwise return the Type_info for the static type of the expr. */ ! 452: return get_typeid (type); ! 453: } ! 454: ! 455: /* Return the Type_info object for TYPE, creating it if necessary. */ ! 456: tree ! 457: get_typeid (type) ! 458: tree type; ! 459: { ! 460: if (type == error_mark_node) ! 461: return error_mark_node; ! 462: ! 463: /* Is it useful (and/or correct) to have different typeids for `T &' ! 464: and `T'? */ ! 465: if (TREE_CODE (type) == REFERENCE_TYPE) ! 466: type = TREE_TYPE (type); ! 467: ! 468: /* build reference to static Type_info */ ! 469: #if 1 ! 470: sorry ("finding Type_info for a type"); ! 471: return error_mark_node; ! 472: #else ! 473: register tree t = TYPE_TINFO (type); ! 474: ! 475: if (t) ! 476: return t; ! 477: ! 478: /* ... */ ! 479: ! 480: #endif ! 481: } ! 482: ! 483: /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working ! 484: paper. */ ! 485: tree ! 486: build_dynamic_cast (type, expr) ! 487: tree type, expr; ! 488: { ! 489: enum tree_code tc = TREE_CODE (type); ! 490: tree exprtype = TREE_TYPE (expr); ! 491: enum tree_code ec = TREE_CODE (exprtype); ! 492: tree retval; ! 493: ! 494: if (type == error_mark_node || expr == error_mark_node) ! 495: return error_mark_node; ! 496: ! 497: switch (tc) ! 498: { ! 499: case POINTER_TYPE: ! 500: if (TREE_TYPE (type) == void_type_node) ! 501: break; ! 502: /* else fall through */ ! 503: case REFERENCE_TYPE: ! 504: if (TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE ! 505: && TYPE_SIZE (TREE_TYPE (type)) != NULL_TREE) ! 506: break; ! 507: /* else fall through */ ! 508: default: ! 509: cp_error ("`%#T' is not a valid type argument for dynamic_cast", type); ! 510: error ("(must be either pointer or reference to defined class or void *)"); ! 511: return error_mark_node; ! 512: } ! 513: ! 514: /* Apply trivial conversion T -> T& for dereferenced ptrs. */ ! 515: if (ec == RECORD_TYPE) ! 516: { ! 517: exprtype = build_reference_type (exprtype); ! 518: ec = REFERENCE_TYPE; ! 519: } ! 520: ! 521: /* the TREE_CODE of exprtype must match that of type. */ ! 522: if (ec != tc) ! 523: { ! 524: cp_error ("`%E' (of type `%#T') fails to be of %s type", expr, exprtype, ! 525: tc == POINTER_TYPE ? "pointer" : "reference"); ! 526: return error_mark_node; ! 527: } ! 528: ! 529: /* If *type is an unambiguous accessible base class of *exprtype, ! 530: convert statically. */ ! 531: { ! 532: int distance; ! 533: tree path; ! 534: ! 535: distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1, ! 536: &path); ! 537: if (distance >= 0) ! 538: return build_vbase_path (PLUS_EXPR, type, expr, path, 0); ! 539: } ! 540: ! 541: /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */ ! 542: if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype))) ! 543: { ! 544: /* if TYPE is `void *', return pointer to complete object. */ ! 545: if (tc == POINTER_TYPE && TREE_TYPE (type) == void_type_node) ! 546: { ! 547: /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */ ! 548: if (TREE_CODE (expr) == ADDR_EXPR ! 549: && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL ! 550: && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE) ! 551: return build1 (NOP_EXPR, type, expr); ! 552: ! 553: sorry ("finding pointer to complete object"); ! 554: return build1 (NOP_EXPR, type, expr); ! 555: } ! 556: else ! 557: { ! 558: tree retval; ! 559: ! 560: /* If we got here, we can't convert statically. Therefore, ! 561: dynamic_cast<D&>(b) (b an object) cannot succeed. */ ! 562: if (ec == REFERENCE_TYPE) ! 563: { ! 564: if (TREE_CODE (expr) == VAR_DECL ! 565: && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE) ! 566: { ! 567: cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed", ! 568: expr, type); ! 569: /* cplus_expand_throw (Bad_cast_node); */ ! 570: sorry ("throwing Bad_cast"); ! 571: return error_mark_node; ! 572: } ! 573: } ! 574: /* Ditto for dynamic_cast<D*>(&b). */ ! 575: else if (TREE_CODE (expr) == ADDR_EXPR) ! 576: { ! 577: tree op = TREE_OPERAND (expr, 0); ! 578: if (TREE_CODE (op) == VAR_DECL ! 579: && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE) ! 580: { ! 581: cp_warning ("dynamic_cast of `%E' to `%#T' can never succeed", ! 582: expr, type); ! 583: retval = build_int_2 (0, 0); ! 584: TREE_TYPE (retval) = type; ! 585: return retval; ! 586: } ! 587: } ! 588: /* Build run-time conversion. */ ! 589: sorry ("run-time type conversion"); ! 590: retval = build_int_2 (0, 0); ! 591: TREE_TYPE (retval) = type; ! 592: return retval; ! 593: } ! 594: } ! 595: ! 596: cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'", ! 597: expr, exprtype, type); ! 598: return error_mark_node; ! 599: } ! 600: 1.1 root 601: /* Build and initialize various sorts of descriptors. Every descriptor 602: node has a name associated with it (the name created by mangling). 603: For this reason, we use the identifier as our access to the __*_desc 604: nodes, instead of sticking them directly in the types. Otherwise we 605: would burden all built-in types (and pointer types) with slots that 606: we don't necessarily want to use. 607: 608: For each descriptor we build, we build a variable that contains 609: the descriptor's information. When we need this info at runtime, 610: all we need is access to these variables. 611: 612: Note: these constructors always return the address of the descriptor 613: info, since that is simplest for their mutual interaction. */ 614: 615: static tree 616: build_generic_desc (decl, elems) 617: tree decl; 618: tree elems; 619: { 620: tree init = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE, elems); 621: TREE_CONSTANT (init) = 1; 622: TREE_STATIC (init) = 1; 623: TREE_READONLY (init) = 1; 624: 625: DECL_INITIAL (decl) = init; 626: TREE_STATIC (decl) = 1; 627: layout_decl (decl, 0); 628: finish_decl (decl, init, 0, 0); 629: 630: return IDENTIFIER_AS_DESC (DECL_NAME (decl)); 631: } 632: 633: /* Build an initializer for a __t_desc node. So that we can take advantage 634: of recursion, we accept NULL for TYPE. 635: DEFINITION is greater than zero iff we must define the type descriptor 636: (as opposed to merely referencing it). 1 means treat according to 637: #pragma interface/#pragma implementation rules. 2 means define as 638: global and public, no matter what. */ 639: tree 640: build_t_desc (type, definition) 641: tree type; 642: int definition; 643: { 644: tree tdecl; 645: tree tname, name_string; 646: tree elems, fields; 647: tree parents, vbases, offsets, ivars, methods, target_type; 648: int method_count = 0, field_count = 0; 649: 650: if (type == NULL_TREE) 651: return NULL_TREE; 652: 653: tname = build_t_desc_overload (type); 654: if (IDENTIFIER_AS_DESC (tname) 655: && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname)))) 656: return IDENTIFIER_AS_DESC (tname); 657: 658: tdecl = lookup_name (tname, 0); 659: if (tdecl == NULL_TREE) 660: { 661: tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node); 1.1.1.4 root 662: DECL_EXTERNAL (tdecl) = 1; 1.1 root 663: TREE_PUBLIC (tdecl) = 1; 664: tdecl = pushdecl_top_level (tdecl); 665: } 666: /* If we previously defined it, return the defined result. */ 667: else if (definition && DECL_INITIAL (tdecl)) 668: return IDENTIFIER_AS_DESC (tname); 669: 670: if (definition) 671: { 672: tree taggr = type; 673: /* Let T* and T& be written only when T is written (if T is an aggr). 674: We do this for const, but not for volatile, since volatile 675: is rare and const is not. */ 676: if (!TYPE_VOLATILE (taggr) 677: && (TREE_CODE (taggr) == POINTER_TYPE 678: || TREE_CODE (taggr) == REFERENCE_TYPE) 679: && IS_AGGR_TYPE (TREE_TYPE (taggr))) 680: taggr = TREE_TYPE (taggr); 681: 682: /* If we know that we don't need to write out this type's 683: vtable, then don't write out it's dossier. Somebody 684: else will take care of that. */ 685: if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr)) 686: { 687: if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr)) 688: { 1.1.1.6 ! root 689: TREE_PUBLIC (tdecl) = ! CLASSTYPE_INTERFACE_ONLY (taggr) ! 690: && CLASSTYPE_INTERFACE_KNOWN (taggr); 1.1 root 691: TREE_STATIC (tdecl) = 1; 1.1.1.4 root 692: DECL_EXTERNAL (tdecl) = 0; 1.1 root 693: } 694: else 695: { 696: if (write_virtuals != 0) 697: TREE_PUBLIC (tdecl) = 1; 698: } 699: } 700: else 701: { 1.1.1.4 root 702: DECL_EXTERNAL (tdecl) = 0; 1.1 root 703: TREE_STATIC (tdecl) = 1; 704: TREE_PUBLIC (tdecl) = (definition > 1); 705: } 706: } 707: SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0)); 1.1.1.4 root 708: if (!definition || DECL_EXTERNAL (tdecl)) 1.1 root 709: { 710: /* That's it! */ 711: finish_decl (tdecl, 0, 0, 0); 712: return IDENTIFIER_AS_DESC (tname); 713: } 714: 715: /* Show that we are defining the t_desc for this type. */ 716: DECL_INITIAL (tdecl) = error_mark_node; 717: 718: parents = build_tree_list (NULL_TREE, integer_zero_node); 719: vbases = build_tree_list (NULL_TREE, integer_zero_node); 720: offsets = build_tree_list (NULL_TREE, integer_zero_node); 721: methods = NULL_TREE; 722: ivars = NULL_TREE; 723: 724: if (TYPE_LANG_SPECIFIC (type)) 725: { 726: int i = CLASSTYPE_N_BASECLASSES (type); 727: tree method_vec = CLASSTYPE_METHOD_VEC (type); 728: tree *meth, *end; 729: tree binfos = TYPE_BINFO_BASETYPES (type); 730: tree vb = CLASSTYPE_VBASECLASSES (type); 731: 732: while (--i >= 0) 733: parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents); 734: 735: while (vb) 736: { 737: vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases); 738: offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets); 739: vb = TREE_CHAIN (vb); 740: } 741: 742: if (method_vec) 743: for (meth = TREE_VEC_END (method_vec), 744: end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; ) 745: if (*meth) 746: { 747: methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods); 748: method_count++; 749: } 750: } 751: 752: if (IS_AGGR_TYPE (type)) 753: { 754: for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) 755: if (TREE_CODE (fields) == FIELD_DECL 756: || TREE_CODE (fields) == VAR_DECL) 757: { 758: ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars); 759: field_count++; 760: } 761: ivars = nreverse (ivars); 762: } 763: 764: parents = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), parents, 0); 765: vbases = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), vbases, 0); 766: offsets = finish_table (0, integer_type_node, offsets, 0); 1.1.1.6 ! root 767: if (methods == NULL_TREE) ! 768: methods = null_pointer_node; ! 769: else ! 770: methods = build_unary_op (ADDR_EXPR, ! 771: finish_table (0, __m_desc_type_node, methods, 0), ! 772: 0); ! 773: if (ivars == NULL_TREE) ! 774: ivars = null_pointer_node; ! 775: else ! 776: ivars = build_unary_op (ADDR_EXPR, ! 777: finish_table (0, __i_desc_type_node, ivars, 0), ! 778: 0); 1.1 root 779: if (TREE_TYPE (type)) 780: target_type = build_t_desc (TREE_TYPE (type), definition); 781: else 782: target_type = integer_zero_node; 783: 784: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname))); 785: 786: elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0), 787: tree_cons (NULL_TREE, 788: TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node, 789: /* really should use bitfield initialization here. */ 790: tree_cons (NULL_TREE, integer_zero_node, 791: tree_cons (NULL_TREE, target_type, 792: tree_cons (NULL_TREE, build_int_2 (field_count, 2), 793: tree_cons (NULL_TREE, build_int_2 (method_count, 2), 1.1.1.6 ! root 794: tree_cons (NULL_TREE, ivars, ! 795: tree_cons (NULL_TREE, methods, 1.1 root 796: tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0), 797: tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0), 798: build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0)))))))))))); 799: return build_generic_desc (tdecl, elems); 800: } 801: 802: /* Build an initializer for a __i_desc node. */ 803: tree 804: build_i_desc (decl) 805: tree decl; 806: { 807: tree elems, name_string; 808: tree taggr; 809: 810: name_string = DECL_NAME (decl); 811: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string))); 812: 813: /* Now decide whether this ivar should cause it's type to get 814: def'd or ref'd in this file. If the type we are looking at 815: has a proxy definition, we look at the proxy (i.e., a 816: `foo *' is equivalent to a `foo'). */ 817: taggr = TREE_TYPE (decl); 818: 819: if ((TREE_CODE (taggr) == POINTER_TYPE 820: || TREE_CODE (taggr) == REFERENCE_TYPE) 821: && TYPE_VOLATILE (taggr) == 0) 822: taggr = TREE_TYPE (taggr); 823: 824: elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0), 825: tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl), 826: build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl), 827: ! IS_AGGR_TYPE (taggr))))); 828: taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems); 829: TREE_CONSTANT (taggr) = 1; 830: TREE_STATIC (taggr) = 1; 831: TREE_READONLY (taggr) = 1; 832: return taggr; 833: } 834: 835: /* Build an initializer for a __m_desc node. */ 836: tree 837: build_m_desc (decl) 838: tree decl; 839: { 840: tree taggr, elems, name_string; 841: tree parm_count, req_count, vindex, vcontext; 842: tree parms; 843: int p_count, r_count; 844: tree parm_types = NULL_TREE; 845: 846: for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0; 847: parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++) 848: { 849: taggr = TREE_VALUE (parms); 850: if ((TREE_CODE (taggr) == POINTER_TYPE 851: || TREE_CODE (taggr) == REFERENCE_TYPE) 852: && TYPE_VOLATILE (taggr) == 0) 853: taggr = TREE_TYPE (taggr); 854: 855: parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms), 856: ! IS_AGGR_TYPE (taggr)), 857: parm_types); 858: if (TREE_PURPOSE (parms) == NULL_TREE) 859: r_count++; 860: } 861: 862: parm_types = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), 863: nreverse (parm_types), 0); 864: parm_count = build_int_2 (p_count, 0); 865: req_count = build_int_2 (r_count, 0); 866: 867: if (DECL_VINDEX (decl)) 868: vindex = DECL_VINDEX (decl); 869: else 870: vindex = integer_zero_node; 1.1.1.4 root 871: if (DECL_CONTEXT (decl) 872: && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't') 1.1 root 873: vcontext = build_t_desc (DECL_CONTEXT (decl), 0); 874: else 875: vcontext = integer_zero_node; 876: name_string = DECL_NAME (decl); 877: if (name_string == NULL) 878: name_string = DECL_ASSEMBLER_NAME (decl); 879: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string))); 880: 881: /* Now decide whether the return type of this mvar 882: should cause it's type to get def'd or ref'd in this file. 883: If the type we are looking at has a proxy definition, 884: we look at the proxy (i.e., a `foo *' is equivalent to a `foo'). */ 885: taggr = TREE_TYPE (TREE_TYPE (decl)); 886: 887: if ((TREE_CODE (taggr) == POINTER_TYPE 888: || TREE_CODE (taggr) == REFERENCE_TYPE) 889: && TYPE_VOLATILE (taggr) == 0) 890: taggr = TREE_TYPE (taggr); 891: 892: elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0), 893: tree_cons (NULL_TREE, vindex, 894: tree_cons (NULL_TREE, vcontext, 895: tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)), 896: ! IS_AGGR_TYPE (taggr)), 897: tree_cons (NULL_TREE, build_c_cast (TYPE_POINTER_TO (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)), 898: tree_cons (NULL_TREE, parm_count, 899: tree_cons (NULL_TREE, req_count, 900: build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0))))))))); 901: 902: taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems); 903: TREE_CONSTANT (taggr) = 1; 904: TREE_STATIC (taggr) = 1; 905: TREE_READONLY (taggr) = 1; 906: return taggr; 907: } 908: 909: /* Conditionally emit code to set up an unwind-protect for the 910: garbage collector. If this function doesn't do anything that involves 911: the garbage collector, then do nothing. Otherwise, call __gc_push 912: at the beginning and __gc_pop at the end. 913: 914: NOTE! The __gc_pop function must operate transparently, since 915: it comes where the logical return label lies. This means that 916: at runtime *it* must preserve any return value registers. */ 917: 918: void 919: expand_gc_prologue_and_epilogue () 920: { 921: extern tree maybe_gc_cleanup; 922: struct rtx_def *last_parm_insn, *mark; 923: extern struct rtx_def *get_last_insn (); 924: extern struct rtx_def *get_first_nonparm_insn (); 925: extern struct rtx_def *previous_insn (); 926: tree action; 927: 928: /* If we didn't need the obstack, don't cons any space. */ 929: if (current_function_obstack_index == 0 930: || current_function_obstack_usage == 0) 931: return; 932: 933: mark = get_last_insn (); 934: last_parm_insn = get_first_nonparm_insn (); 935: if (last_parm_insn == 0) last_parm_insn = mark; 936: else last_parm_insn = previous_insn (last_parm_insn); 937: 938: action = build_function_call (gc_push_fndecl, 939: build_tree_list (NULL_TREE, size_int (++current_function_obstack_index))); 940: expand_expr_stmt (action); 941: 942: reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn); 943: 944: /* This will be expanded as a cleanup. */ 945: TREE_VALUE (maybe_gc_cleanup) 946: = build_function_call (gc_pop_fndecl, NULL_TREE); 947: } 948: 949: /* Some day we'll use this function as a call-back and clean 950: up all the unnecessary gc dribble that we otherwise create. */ 951: void 952: lang_expand_end_bindings (first, last) 953: struct rtx_def *first, *last; 954: { 955: } 956: 957: void 958: init_gc_processing () 959: { 960: tree parmtypes = hash_tree_chain (class_star_type_node, 961: hash_tree_chain (integer_type_node, NULL_TREE)); 962: gc_protect_fndecl = define_function ("__gc_protect", 963: build_function_type (class_star_type_node, parmtypes), 964: NOT_BUILT_IN, 0, 0); 965: 966: parmtypes = hash_tree_chain (integer_type_node, NULL_TREE); 967: gc_unprotect_fndecl = define_function ("__gc_unprotect", 968: build_function_type (void_type_node, parmtypes), 969: NOT_BUILT_IN, 0, 0); 970: 971: gc_push_fndecl = define_function ("__gc_push", 972: TREE_TYPE (gc_unprotect_fndecl), 973: NOT_BUILT_IN, 0, 0); 974: 975: gc_pop_fndecl = define_function ("__gc_pop", 976: build_function_type (void_type_node, 977: void_list_node), 978: NOT_BUILT_IN, 0, 0); 979: gc_nonobject = build_int_2 (0x80000000, 0); 980: gc_visible = build_int_2 (0x40000000, 0); 981: gc_white = integer_zero_node; 982: gc_offwhite = build_int_2 (0x10000000, 0); 983: gc_grey = build_int_2 (0x20000000, 0); 984: gc_black = build_int_2 (0x30000000, 0); 985: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.