|
|
1.1 root 1: /* Garbage collection primitives for GNU C++. 1.1.1.2 ! root 2: Copyright (C) 1992, 1993, 1994, 1995 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 1.1.1.2 ! root 19: the Free Software Foundation, 59 Temple Place - Suite 330, ! 20: Boston, MA 02111-1307, USA. */ 1.1 root 21: 22: 23: #include "config.h" 24: #include "tree.h" 25: #include "cp-tree.h" 26: #include "flags.h" 1.1.1.2 ! root 27: #include "output.h" 1.1 root 28: 29: #undef NULL 30: #define NULL 0 31: 32: extern tree define_function (); 33: extern tree build_t_desc_overload (); 1.1.1.2 ! root 34: extern struct obstack *permanent_obstack; 1.1 root 35: 36: /* This is the function decl for the (pseudo-builtin) __gc_protect 37: function. Args are (class *value, int index); Returns value. */ 38: tree gc_protect_fndecl; 39: 40: /* This is the function decl for the (pseudo-builtin) __gc_unprotect 41: function. Args are (int index); void return. */ 42: tree gc_unprotect_fndecl; 43: 44: /* This is the function decl for the (pseudo-builtin) __gc_push 45: function. Args are (int length); void return. */ 46: tree gc_push_fndecl; 47: 48: /* This is the function decl for the (pseudo-builtin) __gc_pop 49: function. Args are void; void return. */ 50: tree gc_pop_fndecl; 51: 52: /* Special integers that are used to represent bits in gc-safe objects. */ 53: tree gc_nonobject; 54: tree gc_visible; 55: tree gc_white; 56: tree gc_offwhite; 57: tree gc_grey; 58: tree gc_black; 59: 60: /* in c-common.c */ 61: extern tree combine_strings PROTO((tree)); 62: 63: /* Predicate that returns non-zero if TYPE needs some kind of 64: entry for the GC. Returns zero otherwise. */ 65: int 66: type_needs_gc_entry (type) 67: tree type; 68: { 69: tree ttype = type; 70: 71: if (! flag_gc || type == error_mark_node) 72: return 0; 73: 74: /* Aggregate types need gc entries if any of their members 75: need gc entries. */ 76: if (IS_AGGR_TYPE (type)) 77: { 78: tree binfos; 79: tree fields = TYPE_FIELDS (type); 80: int i; 81: 82: /* We don't care about certain pointers. Pointers 83: to virtual baseclasses are always up front. We also 84: cull out virtual function table pointers because it's 85: easy, and it simplifies the logic.*/ 86: while (fields 87: && (DECL_NAME (fields) == NULL_TREE 88: || VFIELD_NAME_P (DECL_NAME (fields)) 89: || VBASE_NAME_P (DECL_NAME (fields)) 90: || !strcmp (IDENTIFIER_POINTER (DECL_NAME (fields)), "__bits"))) 91: fields = TREE_CHAIN (fields); 92: 93: while (fields) 94: { 95: if (type_needs_gc_entry (TREE_TYPE (fields))) 96: return 1; 97: fields = TREE_CHAIN (fields); 98: } 99: 100: binfos = TYPE_BINFO_BASETYPES (type); 101: if (binfos) 102: for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--) 103: if (type_needs_gc_entry (BINFO_TYPE (TREE_VEC_ELT (binfos, i)))) 104: return 1; 105: 106: return 0; 107: } 108: 109: while (TREE_CODE (ttype) == ARRAY_TYPE 110: && TREE_CODE (TREE_TYPE (ttype)) == ARRAY_TYPE) 111: ttype = TREE_TYPE (ttype); 112: if ((TREE_CODE (ttype) == POINTER_TYPE 113: || TREE_CODE (ttype) == ARRAY_TYPE 114: || TREE_CODE (ttype) == REFERENCE_TYPE) 115: && IS_AGGR_TYPE (TREE_TYPE (ttype)) 1.1.1.2 ! root 116: && CLASSTYPE_RTTI (TREE_TYPE (ttype))) 1.1 root 117: return 1; 118: 119: return 0; 120: } 121: 122: /* Predicate that returns non-zero iff FROM is safe from the GC. 123: 124: If TO is nonzero, it means we know that FROM is being stored 125: in TO, which make make it safe. */ 126: int 127: value_safe_from_gc (to, from) 128: tree to, from; 129: { 130: /* First, return non-zero for easy cases: parameters, 131: static variables. */ 132: if (TREE_CODE (from) == PARM_DECL 133: || (TREE_CODE (from) == VAR_DECL 134: && TREE_STATIC (from))) 135: return 1; 136: 137: /* If something has its address taken, it cannot be 138: in the heap, so it doesn't need to be protected. */ 139: if (TREE_CODE (from) == ADDR_EXPR || TREE_REFERENCE_EXPR (from)) 140: return 1; 141: 142: /* If we are storing into a static variable, then what 143: we store will be safe from the gc. */ 144: if (to && TREE_CODE (to) == VAR_DECL 145: && TREE_STATIC (to)) 146: return 1; 147: 148: /* Now recurse on structure of FROM. */ 149: switch (TREE_CODE (from)) 150: { 151: case COMPONENT_REF: 152: /* These guys are special, and safe. */ 153: if (TREE_CODE (TREE_OPERAND (from, 1)) == FIELD_DECL 154: && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (from, 1))) 155: || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (from, 1))))) 156: return 1; 157: /* fall through... */ 158: case NOP_EXPR: 159: case CONVERT_EXPR: 160: case NON_LVALUE_EXPR: 161: case WITH_CLEANUP_EXPR: 162: case SAVE_EXPR: 163: case PREDECREMENT_EXPR: 164: case PREINCREMENT_EXPR: 165: case POSTDECREMENT_EXPR: 166: case POSTINCREMENT_EXPR: 167: if (value_safe_from_gc (to, TREE_OPERAND (from, 0))) 168: return 1; 169: break; 170: 171: case VAR_DECL: 172: case PARM_DECL: 173: /* We can safely pass these things as parameters to functions. */ 174: if (to == 0) 175: return 1; 176: 177: case ARRAY_REF: 178: case INDIRECT_REF: 179: case RESULT_DECL: 180: case OFFSET_REF: 181: case CALL_EXPR: 182: case METHOD_CALL_EXPR: 183: break; 184: 185: case COMPOUND_EXPR: 186: case TARGET_EXPR: 187: if (value_safe_from_gc (to, TREE_OPERAND (from, 1))) 188: return 1; 189: break; 190: 191: case COND_EXPR: 192: if (value_safe_from_gc (to, TREE_OPERAND (from, 1)) 193: && value_safe_from_gc (to, TREE_OPERAND (from, 2))) 194: return 1; 195: break; 196: 197: case PLUS_EXPR: 198: case MINUS_EXPR: 199: if ((type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 0))) 200: || value_safe_from_gc (to, TREE_OPERAND (from, 0))) 201: && (type_needs_gc_entry (TREE_TYPE (TREE_OPERAND (from, 1))) == 0 202: || value_safe_from_gc (to, TREE_OPERAND (from, 1)))) 203: return 1; 204: break; 205: 206: case RTL_EXPR: 207: /* Every time we build an RTL_EXPR in the front-end, we must 208: ensure that everything in it is safe from the garbage collector. 209: ??? This has only been done for `build_new'. */ 210: return 1; 211: 212: default: 213: my_friendly_abort (41); 214: } 215: 216: if (to == 0) 217: return 0; 218: 219: /* FROM wasn't safe. But other properties of TO might make it safe. */ 220: switch (TREE_CODE (to)) 221: { 222: case VAR_DECL: 223: case PARM_DECL: 224: /* We already culled out static VAR_DECLs above. */ 225: return 0; 226: 227: case COMPONENT_REF: 228: /* These guys are special, and safe. */ 229: if (TREE_CODE (TREE_OPERAND (to, 1)) == FIELD_DECL 230: && (VFIELD_NAME_P (DECL_NAME (TREE_OPERAND (to, 1))) 231: || VBASE_NAME_P (DECL_NAME (TREE_OPERAND (to, 1))))) 232: return 1; 233: /* fall through... */ 234: 235: case NOP_EXPR: 236: case NON_LVALUE_EXPR: 237: case WITH_CLEANUP_EXPR: 238: case SAVE_EXPR: 239: case PREDECREMENT_EXPR: 240: case PREINCREMENT_EXPR: 241: case POSTDECREMENT_EXPR: 242: case POSTINCREMENT_EXPR: 243: return value_safe_from_gc (TREE_OPERAND (to, 0), from); 244: 245: case COMPOUND_EXPR: 246: case TARGET_EXPR: 247: return value_safe_from_gc (TREE_OPERAND (to, 1), from); 248: 249: case COND_EXPR: 250: return (value_safe_from_gc (TREE_OPERAND (to, 1), from) 251: && value_safe_from_gc (TREE_OPERAND (to, 2), from)); 252: 253: case INDIRECT_REF: 254: case ARRAY_REF: 255: /* This used to be 0, but our current restricted model 256: allows this to be 1. We'll never get arrays this way. */ 257: return 1; 258: 259: default: 260: my_friendly_abort (42); 261: } 262: 263: /* Catch-all case is that TO/FROM is not safe. */ 264: return 0; 265: } 266: 267: /* Function to build a static GC entry for DECL. TYPE is DECL's type. 268: 269: For objects of type `class *', this is just an entry in the 270: static vector __PTR_LIST__. 271: 272: For objects of type `class[]', this requires building an entry 273: in the static vector __ARR_LIST__. 274: 275: For aggregates, this records all fields of type `class *' 276: and `class[]' in the respective lists above. */ 277: void 278: build_static_gc_entry (decl, type) 279: tree decl; 280: tree type; 281: { 282: /* Now, figure out what sort of entry to build. */ 283: if (TREE_CODE (type) == POINTER_TYPE 284: || TREE_CODE (type) == REFERENCE_TYPE) 285: assemble_gc_entry (IDENTIFIER_POINTER (DECL_NAME (decl))); 286: else if (TREE_CODE (type) == RECORD_TYPE) 287: { 288: tree ref = get_temp_name (build_reference_type (type), 1); 289: DECL_INITIAL (ref) = build1 (ADDR_EXPR, TREE_TYPE (ref), decl); 290: TREE_CONSTANT (DECL_INITIAL (ref)) = 1; 1.1.1.2 ! root 291: cp_finish_decl (ref, DECL_INITIAL (ref), NULL_TREE, 0, 0); 1.1 root 292: } 293: else 294: { 295: /* Not yet implemented. 296: 297: Cons up a static variable that holds address and length info 298: and add that to ___ARR_LIST__. */ 299: my_friendly_abort (43); 300: } 301: } 302: 303: /* Protect FROM from the GC, assuming FROM is going to be 304: stored into TO. We handle three cases for TO here: 305: 306: case 1: TO is a stack variable. 307: case 2: TO is zero (which means it is a parameter). 308: case 3: TO is a return value. */ 309: 310: tree 311: protect_value_from_gc (to, from) 312: tree to, from; 313: { 314: if (to == 0) 315: { 316: tree cleanup; 317: 318: to = get_temp_regvar (TREE_TYPE (from), from); 319: 320: /* Convert from integer to list form since we'll use it twice. */ 321: DECL_GC_OFFSET (to) = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to)); 322: cleanup = build_function_call (gc_unprotect_fndecl, 323: DECL_GC_OFFSET (to)); 324: 1.1.1.2 ! root 325: if (! cp_expand_decl_cleanup (to, cleanup)) 1.1 root 326: { 327: compiler_error ("cannot unprotect parameter in this scope"); 328: return error_mark_node; 329: } 330: } 331: 332: /* Should never need to protect a value that's headed for static storage. */ 333: if (TREE_STATIC (to)) 334: my_friendly_abort (44); 335: 336: switch (TREE_CODE (to)) 337: { 338: case COMPONENT_REF: 339: case INDIRECT_REF: 340: return protect_value_from_gc (TREE_OPERAND (to, 0), from); 341: 342: case VAR_DECL: 343: case PARM_DECL: 344: { 345: tree rval; 346: if (DECL_GC_OFFSET (to) == NULL_TREE) 347: { 348: /* Because of a cast or a conversion, we might stick 349: a value into a variable that would not normally 350: have a GC entry. */ 351: DECL_GC_OFFSET (to) = size_int (++current_function_obstack_index); 352: } 353: 354: if (TREE_CODE (DECL_GC_OFFSET (to)) != TREE_LIST) 355: { 356: DECL_GC_OFFSET (to) 357: = build_tree_list (NULL_TREE, DECL_GC_OFFSET (to)); 358: } 359: 360: current_function_obstack_usage = 1; 361: rval = build_function_call (gc_protect_fndecl, 362: tree_cons (NULL_TREE, from, 363: DECL_GC_OFFSET (to))); 364: TREE_TYPE (rval) = TREE_TYPE (from); 365: return rval; 366: } 367: } 368: 369: /* If we fall through the switch, assume we lost. */ 370: my_friendly_abort (45); 371: /* NOTREACHED */ 372: return NULL_TREE; 373: } 374: 375: /* Given the expression EXP of type `class *', return the head 376: of the object pointed to by EXP. */ 377: tree 378: build_headof (exp) 379: tree exp; 380: { 381: tree type = TREE_TYPE (exp); 382: tree vptr, offset; 383: 384: if (TREE_CODE (type) != POINTER_TYPE) 385: { 386: error ("`headof' applied to non-pointer type"); 387: return error_mark_node; 388: } 1.1.1.2 ! root 389: type = TREE_TYPE (type); 1.1 root 390: 1.1.1.2 ! root 391: if (!TYPE_VIRTUAL_P (type) || CLASSTYPE_VFIELD (type) == NULL_TREE) ! 392: return exp; 1.1 root 393: 1.1.1.2 ! root 394: vptr = fold (size_binop (PLUS_EXPR, ! 395: size_binop (FLOOR_DIV_EXPR, ! 396: DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (type)), ! 397: size_int (BITS_PER_UNIT)), ! 398: exp)); ! 399: vptr = build1 (INDIRECT_REF, build_pointer_type (vtable_entry_type), vptr); 1.1 root 400: 1.1.1.2 ! root 401: if (flag_vtable_thunks) ! 402: offset = build_array_ref (vptr, integer_zero_node); ! 403: else ! 404: offset = build_component_ref (build_array_ref (vptr, integer_zero_node), ! 405: delta_identifier, ! 406: NULL_TREE, 0); ! 407: ! 408: type = build_type_variant (ptr_type_node, TREE_READONLY (exp), ! 409: TREE_THIS_VOLATILE (exp)); ! 410: return build (PLUS_EXPR, type, exp, ! 411: convert (ptrdiff_type_node, offset)); 1.1 root 412: } 413: 1.1.1.2 ! root 414: /* Return the type_info node associated with the expression EXP. If EXP is 1.1 root 415: a reference to a polymorphic class, return the dynamic type; otherwise 416: return the static type of the expression. */ 417: tree 418: build_typeid (exp) 419: tree exp; 420: { 421: tree type; 422: 1.1.1.2 ! root 423: if (!flag_rtti) ! 424: cp_error ("cannot take typeid of object when -frtti is not specified"); ! 425: 1.1 root 426: if (exp == error_mark_node) 427: return error_mark_node; 428: 429: type = TREE_TYPE (exp); 1.1.1.2 ! root 430: ! 431: /* Strip top-level cv-qualifiers. */ ! 432: type = TYPE_MAIN_VARIANT (type); ! 433: 1.1 root 434: /* if b is an instance of B, typeid(b) == typeid(B). Do this before 435: reference trickiness. */ 436: if (TREE_CODE (exp) == VAR_DECL && TREE_CODE (type) == RECORD_TYPE) 437: return get_typeid (type); 438: 1.1.1.2 ! root 439: /* peel back references, so they match. */ ! 440: if (TREE_CODE (type) == REFERENCE_TYPE) ! 441: type = TREE_TYPE (type); ! 442: ! 443: /* Peel off cv qualifiers. */ ! 444: type = TYPE_MAIN_VARIANT (type); ! 445: 1.1 root 446: /* Apply trivial conversion T -> T& for dereferenced ptrs. */ 447: if (TREE_CODE (type) == RECORD_TYPE) 448: type = build_reference_type (type); 449: 1.1.1.2 ! root 450: /* If exp is a reference to polymorphic type, get the real type_info. */ 1.1 root 451: if (TREE_CODE (type) == REFERENCE_TYPE && TYPE_VIRTUAL_P (TREE_TYPE (type))) 452: { 1.1.1.2 ! root 453: /* build reference to type_info from vtable. */ ! 454: tree t; ! 455: ! 456: if (flag_vtable_thunks) ! 457: t = build_vfn_ref ((tree *) NULL_TREE, exp, integer_one_node); ! 458: else ! 459: t = build_vfn_ref ((tree *) NULL_TREE, exp, integer_zero_node); ! 460: ! 461: TREE_TYPE (t) = build_pointer_type (__class_desc_type_node); ! 462: t = build_indirect_ref (t, NULL); ! 463: return t; 1.1 root 464: } 465: 1.1.1.2 ! root 466: /* otherwise return the type_info for the static type of the expr. */ 1.1 root 467: return get_typeid (type); 468: } 469: 1.1.1.2 ! root 470: /* Return the type_info object for TYPE, creating it if necessary. */ 1.1 root 471: tree 472: get_typeid (type) 473: tree type; 474: { 1.1.1.2 ! root 475: tree t, td; ! 476: 1.1 root 477: if (type == error_mark_node) 478: return error_mark_node; 479: 480: /* Is it useful (and/or correct) to have different typeids for `T &' 481: and `T'? */ 482: if (TREE_CODE (type) == REFERENCE_TYPE) 483: type = TREE_TYPE (type); 484: 1.1.1.2 ! root 485: td = build_t_desc (type, 1); ! 486: if (td == error_mark_node) ! 487: return error_mark_node; ! 488: ! 489: t = TREE_OPERAND (td, 0); ! 490: return t; ! 491: } 1.1 root 492: 1.1.1.2 ! root 493: /* Get a bad_cast node for the program to throw... 1.1 root 494: 1.1.1.2 ! root 495: See libstdc++::exception{,.cc} for __bad_cast_object */ ! 496: tree ! 497: get_bad_cast_node () ! 498: { ! 499: static tree t; ! 500: if (t == NULL_TREE ! 501: && (t = lookup_name (get_identifier ("__bad_cast_object"), 0)) ! 502: == NULL_TREE) ! 503: { ! 504: error ("you must #include <typeinfo>"); ! 505: return error_mark_node; ! 506: } ! 507: return t; 1.1 root 508: } 509: 510: /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working 511: paper. */ 512: tree 513: build_dynamic_cast (type, expr) 514: tree type, expr; 515: { 516: enum tree_code tc = TREE_CODE (type); 517: tree exprtype = TREE_TYPE (expr); 518: enum tree_code ec = TREE_CODE (exprtype); 519: tree retval; 520: 521: if (type == error_mark_node || expr == error_mark_node) 522: return error_mark_node; 523: 524: switch (tc) 525: { 526: case POINTER_TYPE: 1.1.1.2 ! root 527: if (ec == REFERENCE_TYPE) ! 528: { ! 529: expr = convert_from_reference (expr); ! 530: exprtype = TREE_TYPE (expr); ! 531: ec = TREE_CODE (exprtype); ! 532: } ! 533: if (ec != POINTER_TYPE) ! 534: goto fail; ! 535: if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE) ! 536: goto fail; ! 537: if (TYPE_SIZE (TREE_TYPE (exprtype)) == 0) ! 538: goto fail; ! 539: if (TREE_READONLY (TREE_TYPE (exprtype)) && ! 540: ! TYPE_READONLY (TREE_TYPE (type))) ! 541: goto fail; ! 542: if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node) 1.1 root 543: break; 544: /* else fall through */ 545: case REFERENCE_TYPE: 546: if (TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE 547: && TYPE_SIZE (TREE_TYPE (type)) != NULL_TREE) 548: break; 549: /* else fall through */ 550: default: 1.1.1.2 ! root 551: goto fail; 1.1 root 552: } 553: 554: /* Apply trivial conversion T -> T& for dereferenced ptrs. */ 555: if (ec == RECORD_TYPE) 556: { 1.1.1.2 ! root 557: exprtype = build_type_variant (exprtype, TREE_READONLY (expr), ! 558: TREE_THIS_VOLATILE (expr)); 1.1 root 559: exprtype = build_reference_type (exprtype); 1.1.1.2 ! root 560: expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT, ! 561: LOOKUP_NORMAL, NULL_TREE); 1.1 root 562: ec = REFERENCE_TYPE; 563: } 1.1.1.2 ! root 564: ! 565: if (tc == REFERENCE_TYPE) 1.1 root 566: { 1.1.1.2 ! root 567: if (ec != REFERENCE_TYPE) ! 568: goto fail; ! 569: if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE) ! 570: goto fail; ! 571: if (TYPE_SIZE (TREE_TYPE (exprtype)) == 0) ! 572: goto fail; 1.1 root 573: } 574: 575: /* If *type is an unambiguous accessible base class of *exprtype, 576: convert statically. */ 577: { 578: int distance; 579: tree path; 580: 581: distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1, 582: &path); 583: if (distance >= 0) 584: return build_vbase_path (PLUS_EXPR, type, expr, path, 0); 585: } 586: 587: /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */ 588: if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype))) 589: { 590: /* if TYPE is `void *', return pointer to complete object. */ 1.1.1.2 ! root 591: if (tc == POINTER_TYPE ! 592: && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node) 1.1 root 593: { 594: /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */ 595: if (TREE_CODE (expr) == ADDR_EXPR 596: && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL 597: && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE) 598: return build1 (NOP_EXPR, type, expr); 599: 1.1.1.2 ! root 600: return build_headof (expr); 1.1 root 601: } 602: else 603: { 604: tree retval; 1.1.1.2 ! root 605: tree result, td1, td2, elems, tmp1, expr1; 1.1 root 606: 607: /* If we got here, we can't convert statically. Therefore, 608: dynamic_cast<D&>(b) (b an object) cannot succeed. */ 609: if (ec == REFERENCE_TYPE) 610: { 611: if (TREE_CODE (expr) == VAR_DECL 612: && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE) 613: { 614: cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed", 615: expr, type); 1.1.1.2 ! root 616: return build_throw (get_bad_cast_node ()); 1.1 root 617: } 618: } 619: /* Ditto for dynamic_cast<D*>(&b). */ 620: else if (TREE_CODE (expr) == ADDR_EXPR) 621: { 622: tree op = TREE_OPERAND (expr, 0); 623: if (TREE_CODE (op) == VAR_DECL 624: && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE) 625: { 1.1.1.2 ! root 626: cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed", 1.1 root 627: expr, type); 628: retval = build_int_2 (0, 0); 629: TREE_TYPE (retval) = type; 630: return retval; 631: } 632: } 1.1.1.2 ! root 633: ! 634: expr1 = expr; ! 635: if (tc == REFERENCE_TYPE) ! 636: expr1 = build_unary_op (ADDR_EXPR, expr1, 0); ! 637: 1.1 root 638: /* Build run-time conversion. */ 1.1.1.2 ! root 639: expr1 = build_headof (expr1); ! 640: ! 641: if (ec == POINTER_TYPE) ! 642: td1 = build_typeid (build_indirect_ref (expr, NULL_PTR)); ! 643: else ! 644: td1 = build_typeid (expr); ! 645: ! 646: if (tc == POINTER_TYPE) ! 647: td2 = get_typeid (TREE_TYPE (type)); ! 648: else ! 649: td2 = get_typeid (type); ! 650: ! 651: elems = tree_cons (NULL_TREE, td2, ! 652: tree_cons (NULL_TREE, build_int_2 (1, 0), ! 653: tree_cons (NULL_TREE, expr1, NULL_TREE))); ! 654: result = build_method_call (td1, ! 655: get_identifier ("__rtti_match"), elems, NULL_TREE, LOOKUP_NORMAL); ! 656: ! 657: if (tc == REFERENCE_TYPE) ! 658: { ! 659: expr1 = build_throw (get_bad_cast_node ()); ! 660: expr1 = build_compound_expr (tree_cons (NULL_TREE, expr1, ! 661: build_tree_list (NULL_TREE, convert (type, integer_zero_node)))); ! 662: TREE_TYPE (expr1) = type; ! 663: return build (COND_EXPR, type, result, result, expr1); ! 664: } ! 665: ! 666: /* Now back to the type we want from a void*. */ ! 667: result = convert (type, result); ! 668: return result; 1.1 root 669: } 670: } 671: 1.1.1.2 ! root 672: fail: 1.1 root 673: cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'", 674: expr, exprtype, type); 675: return error_mark_node; 676: } 677: 678: /* Build and initialize various sorts of descriptors. Every descriptor 679: node has a name associated with it (the name created by mangling). 680: For this reason, we use the identifier as our access to the __*_desc 681: nodes, instead of sticking them directly in the types. Otherwise we 682: would burden all built-in types (and pointer types) with slots that 683: we don't necessarily want to use. 684: 685: For each descriptor we build, we build a variable that contains 686: the descriptor's information. When we need this info at runtime, 687: all we need is access to these variables. 688: 689: Note: these constructors always return the address of the descriptor 690: info, since that is simplest for their mutual interaction. */ 691: 692: static tree 1.1.1.2 ! root 693: build_generic_desc (tdecl, type, elems) ! 694: tree tdecl; ! 695: tree type; 1.1 root 696: tree elems; 697: { 1.1.1.2 ! root 698: tree init = elems; ! 699: int toplev = global_bindings_p (); ! 700: 1.1 root 701: TREE_CONSTANT (init) = 1; 702: TREE_STATIC (init) = 1; 703: TREE_READONLY (init) = 1; 704: 1.1.1.2 ! root 705: TREE_TYPE (tdecl) = type; ! 706: DECL_INITIAL (tdecl) = init; ! 707: TREE_STATIC (tdecl) = 1; ! 708: DECL_SIZE (tdecl) = NULL_TREE; ! 709: layout_decl (tdecl, 0); ! 710: if (! toplev) ! 711: push_to_top_level (); ! 712: cp_finish_decl (tdecl, init, NULL_TREE, 0, 0); ! 713: if (! toplev) ! 714: pop_from_top_level (); ! 715: ! 716: if (! TREE_USED (tdecl)) ! 717: { ! 718: assemble_external (tdecl); ! 719: TREE_USED (tdecl) = 1; ! 720: } ! 721: ! 722: return IDENTIFIER_AS_DESC (DECL_NAME (tdecl)); ! 723: } ! 724: ! 725: /* Build an initializer for a __bltn_desc node. */ ! 726: static tree ! 727: build_bltn_desc (tdecl, type) ! 728: tree tdecl; ! 729: tree type; ! 730: { ! 731: tree elems, t; ! 732: ! 733: if (type == boolean_type_node) ! 734: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_BOOL"), ! 735: 0, 0); ! 736: else if (type == char_type_node) ! 737: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_CHAR"), ! 738: 0, 0); ! 739: else if (type == short_integer_type_node) ! 740: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_SHORT"), ! 741: 0, 0); ! 742: else if (type == integer_type_node) ! 743: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_INT"), ! 744: 0, 0); ! 745: else if (type == long_integer_type_node) ! 746: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_LONG"), ! 747: 0, 0); ! 748: else if (type == long_long_integer_type_node) ! 749: t = lookup_field (__bltn_desc_type_node, ! 750: get_identifier("_RTTI_BI_LONGLONG"), 0, 0); ! 751: else if (type == float_type_node) ! 752: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_FLOAT"), ! 753: 0, 0); ! 754: else if (type == double_type_node) ! 755: t = lookup_field (__bltn_desc_type_node, ! 756: get_identifier("_RTTI_BI_DOUBLE"), 0, 0); ! 757: else if (type == long_double_type_node) ! 758: t = lookup_field (__bltn_desc_type_node, ! 759: get_identifier("_RTTI_BI_LDOUBLE"), 0, 0); ! 760: else if (type == unsigned_char_type_node) ! 761: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_UCHAR"), ! 762: 0, 0); ! 763: else if (type == short_unsigned_type_node) ! 764: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_USHORT"), ! 765: 0, 0); ! 766: else if (type == unsigned_type_node) ! 767: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_UINT"), ! 768: 0, 0); ! 769: else if (type == long_unsigned_type_node) ! 770: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_ULONG"), ! 771: 0, 0); ! 772: else if (type == long_long_unsigned_type_node) ! 773: t = lookup_field (__bltn_desc_type_node, ! 774: get_identifier("_RTTI_BI_ULONGLONG"), 0, 0); ! 775: else if (type == signed_char_type_node) ! 776: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_SCHAR"), ! 777: 0, 0); ! 778: else if (type == wchar_type_node) ! 779: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_WCHAR"), ! 780: 0, 0); ! 781: else if (type == void_type_node) ! 782: t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_VOID"), ! 783: 0, 0); ! 784: else ! 785: { ! 786: cp_compiler_error ("type `%T' not handled as a built-in type"); ! 787: } ! 788: ! 789: elems = tree_cons (NULL_TREE, t, NULL_TREE); ! 790: return build_generic_desc (tdecl, __bltn_desc_type_node, elems); ! 791: } ! 792: ! 793: /* Build an initializer for a __user_desc node. */ ! 794: static tree ! 795: build_user_desc (tdecl) ! 796: tree tdecl; ! 797: { ! 798: tree elems, name_string, t; ! 799: tree tname = DECL_NAME (tdecl); ! 800: ! 801: name_string = combine_strings (build_string ! 802: (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname))); ! 803: elems = name_string; ! 804: return build_generic_desc (tdecl, __user_desc_type_node, elems); ! 805: } ! 806: ! 807: /* Build an initializer for a __class_type_info node. */ ! 808: static tree ! 809: build_class_desc (tdecl, type) ! 810: tree tdecl; ! 811: tree type; ! 812: { ! 813: tree tname = DECL_NAME (tdecl); ! 814: tree name_string; ! 815: ! 816: int i = CLASSTYPE_N_BASECLASSES (type); ! 817: int n_base = i; ! 818: int base_cnt = 0; ! 819: tree binfos = TYPE_BINFO_BASETYPES (type); ! 820: tree vb = CLASSTYPE_VBASECLASSES (type); ! 821: tree base, elems, access, offset, isvir; ! 822: tree base_list, off_list, acc_list, isvir_list; ! 823: tree t; ! 824: static tree acc_pub = NULL_TREE; ! 825: static tree acc_pro = NULL_TREE; ! 826: static tree acc_pri = NULL_TREE; ! 827: ! 828: if (acc_pub == NULL_TREE) ! 829: { ! 830: acc_pub = lookup_field (__class_desc_type_node, ! 831: get_identifier("_RTTI_ACCESS_PUBLIC"), 0, 0); ! 832: acc_pro = lookup_field (__class_desc_type_node, ! 833: get_identifier("_RTTI_ACCESS_PROTECTED"), 0, 0); ! 834: acc_pri = lookup_field (__class_desc_type_node, ! 835: get_identifier("_RTTI_ACCESS_PRIVATE"), 0, 0); ! 836: } ! 837: ! 838: base_list = build_tree_list (NULL_TREE, integer_zero_node); ! 839: off_list = build_tree_list (NULL_TREE, integer_zero_node); ! 840: acc_list = build_tree_list (NULL_TREE, integer_zero_node); ! 841: isvir_list = build_tree_list (NULL_TREE, integer_zero_node); ! 842: while (--i >= 0) ! 843: { ! 844: tree binfo = TREE_VEC_ELT (binfos, i); ! 845: ! 846: base = build_t_desc (BINFO_TYPE (binfo), 1); ! 847: if (TREE_VIA_VIRTUAL (binfo)) ! 848: { ! 849: tree t = BINFO_TYPE (binfo); ! 850: char *name; ! 851: tree field; ! 852: int off; ! 853: ! 854: name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1); ! 855: sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t)); ! 856: field = lookup_field (type, get_identifier (name), 0, 0); ! 857: offset = size_binop (FLOOR_DIV_EXPR, ! 858: DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT)); ! 859: } ! 860: else ! 861: offset = BINFO_OFFSET (binfo); ! 862: ! 863: if (TREE_VIA_PUBLIC (binfo)) ! 864: access = acc_pub; ! 865: else if (TREE_VIA_PROTECTED (binfo)) ! 866: access = acc_pro; ! 867: else ! 868: access = acc_pri; ! 869: if (TREE_VIA_VIRTUAL (binfo)) ! 870: isvir = build_int_2 (1, 0); ! 871: else ! 872: isvir = build_int_2 (0, 0); ! 873: ! 874: base_list = tree_cons (NULL_TREE, base, base_list); ! 875: isvir_list = tree_cons (NULL_TREE, isvir, isvir_list); ! 876: acc_list = tree_cons (NULL_TREE, access, acc_list); ! 877: off_list = tree_cons (NULL_TREE, offset, off_list); ! 878: base_cnt++; ! 879: } ! 880: #if 0 ! 881: i = n_base; ! 882: while (vb) ! 883: { ! 884: tree b; ! 885: access = acc_pub; ! 886: while (--i >= 0) ! 887: { ! 888: b = TREE_VEC_ELT (binfos, i); ! 889: if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b)) ! 890: { ! 891: if (TREE_VIA_PUBLIC (b)) ! 892: access = acc_pub; ! 893: else if (TREE_VIA_PROTECTED (b)) ! 894: access = acc_pro; ! 895: else ! 896: access = acc_pri; ! 897: break; ! 898: } ! 899: } ! 900: base = build_t_desc (BINFO_TYPE (vb), 1); ! 901: offset = BINFO_OFFSET (vb); ! 902: isvir = build_int_2 (1, 0); ! 903: ! 904: base_list = tree_cons (NULL_TREE, base, base_list); ! 905: isvir_list = tree_cons (NULL_TREE, isvir, isvir_list); ! 906: acc_list = tree_cons (NULL_TREE, access, acc_list); ! 907: off_list = tree_cons (NULL_TREE, offset, off_list); ! 908: ! 909: base_cnt++; ! 910: vb = TREE_CHAIN (vb); ! 911: } ! 912: #endif ! 913: base_list = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), ! 914: base_list, 0); ! 915: off_list = finish_table (NULL_TREE, integer_type_node, ! 916: off_list, 0); ! 917: isvir_list = finish_table (NULL_TREE, integer_type_node, ! 918: isvir_list, 0); ! 919: acc_list = finish_table (NULL_TREE, __access_mode_type_node, ! 920: acc_list, 0); ! 921: 1.1 root 922: 1.1.1.2 ! root 923: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname))); ! 924: ! 925: elems = tree_cons (NULL_TREE, name_string, ! 926: tree_cons (NULL_TREE, default_conversion (base_list), ! 927: tree_cons (NULL_TREE, default_conversion (off_list), ! 928: tree_cons (NULL_TREE, default_conversion (isvir_list), ! 929: tree_cons (NULL_TREE, default_conversion (acc_list), ! 930: tree_cons (NULL_TREE, build_int_2 (base_cnt, 0), NULL_TREE)))))); ! 931: ! 932: return build_generic_desc (tdecl, __class_desc_type_node, elems); 1.1 root 933: } 934: 1.1.1.2 ! root 935: /* Build an initializer for a __pointer_type_info node. */ ! 936: static tree ! 937: build_ptr_desc (tdecl, type) ! 938: tree tdecl; ! 939: tree type; ! 940: { ! 941: tree t, elems; ! 942: ! 943: t = TREE_TYPE (type); ! 944: t = build_t_desc (t, 1); ! 945: t = build_indirect_ref (t, NULL); ! 946: elems = tree_cons (NULL_TREE, t, NULL_TREE); ! 947: return build_generic_desc (tdecl, __ptr_desc_type_node, elems); ! 948: } ! 949: ! 950: /* Build an initializer for a __attr_type_info node. */ ! 951: static tree ! 952: build_attr_desc (tdecl, type) ! 953: tree tdecl; ! 954: tree type; ! 955: { ! 956: tree elems, t, attrval; ! 957: ! 958: if (TYPE_READONLY (type)) ! 959: { ! 960: if (TYPE_VOLATILE (type)) ! 961: attrval = lookup_field (__attr_desc_type_node, ! 962: get_identifier("_RTTI_ATTR_CONSTVOL"), 0, 0); ! 963: else ! 964: attrval = lookup_field (__attr_desc_type_node, ! 965: get_identifier("_RTTI_ATTR_CONST"), 0, 0); ! 966: } ! 967: else ! 968: { ! 969: if (TYPE_VOLATILE (type)) ! 970: attrval = lookup_field (__attr_desc_type_node, ! 971: get_identifier("_RTTI_ATTR_VOLATILE"), 0, 0); ! 972: } ! 973: t = build_t_desc (TYPE_MAIN_VARIANT (type), 1); ! 974: t = build_indirect_ref (t , NULL); ! 975: elems = tree_cons (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE)); ! 976: return build_generic_desc (tdecl, __attr_desc_type_node, elems); ! 977: } ! 978: ! 979: /* Build an initializer for a __func_type_info node. */ ! 980: static tree ! 981: build_func_desc (tdecl) ! 982: tree tdecl; ! 983: { ! 984: tree elems, name_string; ! 985: tree tname = DECL_NAME (tdecl); ! 986: ! 987: name_string = combine_strings (build_string ! 988: (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname))); ! 989: elems = name_string; ! 990: return build_generic_desc (tdecl, __func_desc_type_node, elems); ! 991: } ! 992: ! 993: /* Build an initializer for a __ptmf_type_info node. */ ! 994: static tree ! 995: build_ptmf_desc (tdecl, type) ! 996: tree tdecl; ! 997: tree type; ! 998: { ! 999: tree elems, name_string; ! 1000: tree tname = DECL_NAME (tdecl); ! 1001: ! 1002: name_string = combine_strings (build_string ! 1003: (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname))); ! 1004: elems = name_string; ! 1005: return build_generic_desc (tdecl, __ptmf_desc_type_node, elems); ! 1006: } ! 1007: ! 1008: /* Build an initializer for a __ptmd_type_info node. */ ! 1009: static tree ! 1010: build_ptmd_desc (tdecl, type) ! 1011: tree tdecl; ! 1012: tree type; ! 1013: { ! 1014: tree tc, t, elems; ! 1015: tc = build_t_desc (TYPE_OFFSET_BASETYPE (type), 1); ! 1016: tc = build_indirect_ref (tc , NULL); ! 1017: t = build_t_desc (TREE_TYPE (type), 1); ! 1018: t = build_indirect_ref (t , NULL); ! 1019: elems = tree_cons (NULL_TREE, tc, ! 1020: tree_cons (NULL_TREE, t, NULL_TREE)); ! 1021: return build_generic_desc (tdecl, __ptmd_desc_type_node, elems); ! 1022: } ! 1023: ! 1024: struct uninst_st { ! 1025: tree type; ! 1026: struct uninst_st *next; ! 1027: }; ! 1028: typedef struct uninst_st uninst_node; ! 1029: static uninst_node * uninst_desc = (uninst_node *)NULL; ! 1030: ! 1031: static void ! 1032: add_uninstantiated_desc (type) ! 1033: tree type; ! 1034: { ! 1035: uninst_node *t; ! 1036: ! 1037: t = (uninst_node *) xmalloc (sizeof (struct uninst_st)); ! 1038: t->type = type; ! 1039: t->next = uninst_desc; ! 1040: uninst_desc = t; ! 1041: } ! 1042: ! 1043: /* We may choose to link the emitting of certain high use TDs for certain ! 1044: objects, we do that here. Return the type to link against if such a ! 1045: link exists, otherwise just return TYPE. */ ! 1046: ! 1047: tree ! 1048: get_def_to_follow (type) ! 1049: tree type; ! 1050: { ! 1051: #if 0 ! 1052: /* For now we don't lay out T&, T* TDs with the main TD for the object. */ ! 1053: /* Let T* and T& be written only when T is written (if T is an aggr). ! 1054: We do this for const, but not for volatile, since volatile ! 1055: is rare and const is not. */ ! 1056: if (!TYPE_VOLATILE (taggr) ! 1057: && (TREE_CODE (taggr) == POINTER_TYPE ! 1058: || TREE_CODE (taggr) == REFERENCE_TYPE) ! 1059: && IS_AGGR_TYPE (TREE_TYPE (taggr))) ! 1060: taggr = TREE_TYPE (taggr); ! 1061: #endif ! 1062: return type; ! 1063: } ! 1064: ! 1065: /* build a general type_info node. */ ! 1066: tree ! 1067: build_t_desc (type, definition) ! 1068: tree type; ! 1069: int definition; ! 1070: { ! 1071: tree tdecl; ! 1072: tree tname, name_string; ! 1073: tree elems; ! 1074: tree t, tt, taggr; ! 1075: ! 1076: if (__ptmd_desc_type_node == NULL_TREE) ! 1077: { ! 1078: init_type_desc(); ! 1079: if (__ptmd_desc_type_node) ! 1080: { ! 1081: for ( ; uninst_desc; uninst_desc = uninst_desc->next ) ! 1082: build_t_desc (uninst_desc->type, 1); ! 1083: } ! 1084: } ! 1085: if (__t_desc_type_node == NULL_TREE) ! 1086: { ! 1087: static int warned = 0; ! 1088: if (! warned) ! 1089: { ! 1090: cp_error ("failed to build type descriptor node of '%T', maybe typeinfo.h not included", type); ! 1091: } ! 1092: warned = 1; ! 1093: return error_mark_node; ! 1094: } ! 1095: if (__ptmd_desc_type_node == NULL_TREE) ! 1096: { ! 1097: add_uninstantiated_desc (type); ! 1098: definition = 0; ! 1099: } ! 1100: ! 1101: push_obstacks (&permanent_obstack, &permanent_obstack); ! 1102: tname = build_t_desc_overload (type); ! 1103: ! 1104: if (!IDENTIFIER_AS_DESC (tname)) ! 1105: { ! 1106: tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node); ! 1107: DECL_EXTERNAL (tdecl) = 1; ! 1108: TREE_PUBLIC (tdecl) = 1; ! 1109: tdecl = pushdecl_top_level (tdecl); ! 1110: SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0)); ! 1111: if (!definition) ! 1112: cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0); ! 1113: } ! 1114: else ! 1115: tdecl = TREE_OPERAND (IDENTIFIER_AS_DESC (tname), 0); ! 1116: ! 1117: /* If it's not a definition, don't do anything more. */ ! 1118: if (!definition) ! 1119: return IDENTIFIER_AS_DESC (tname); ! 1120: ! 1121: /* If it has already been written, don't to anything more. */ ! 1122: /* Should this be on tdecl? */ ! 1123: if (TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname))) ! 1124: return IDENTIFIER_AS_DESC (tname); ! 1125: ! 1126: /* If we previously defined it, return the defined result. */ ! 1127: if (DECL_INITIAL (tdecl)) ! 1128: return IDENTIFIER_AS_DESC (tname); ! 1129: ! 1130: taggr = get_def_to_follow (type); ! 1131: ! 1132: /* If we know that we don't need to write out this type's ! 1133: vtable, then don't write out it's type_info. Somebody ! 1134: else will take care of that. */ ! 1135: if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr)) ! 1136: { ! 1137: /* Let's play follow the vtable. */ ! 1138: TREE_PUBLIC (tdecl) = CLASSTYPE_INTERFACE_KNOWN (taggr); ! 1139: DECL_EXTERNAL (tdecl) = CLASSTYPE_INTERFACE_ONLY (taggr); ! 1140: } ! 1141: else ! 1142: { ! 1143: DECL_EXTERNAL (tdecl) = 0; ! 1144: TREE_PUBLIC (tdecl) = (definition > 1); ! 1145: } ! 1146: ! 1147: if (DECL_EXTERNAL (tdecl)) ! 1148: return IDENTIFIER_AS_DESC (tname); ! 1149: ! 1150: /* Show that we are defining the t_desc for this type. */ ! 1151: DECL_INITIAL (tdecl) = error_mark_node; ! 1152: t = DECL_CONTEXT (tdecl); ! 1153: if ( t && TREE_CODE_CLASS (TREE_CODE (t)) == 't') ! 1154: pushclass (t, 2); ! 1155: ! 1156: if (TYPE_VOLATILE (type) || TYPE_READONLY (type)) ! 1157: t = build_attr_desc (tdecl, type); ! 1158: else if (TREE_CODE (type) == ARRAY_TYPE) ! 1159: t = build_ptr_desc (tdecl, type); ! 1160: else if (TREE_CODE (type) == POINTER_TYPE) ! 1161: { ! 1162: if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE) ! 1163: { ! 1164: type = TREE_TYPE (type); ! 1165: t = build_ptmd_desc (tdecl, type); ! 1166: } ! 1167: else ! 1168: { ! 1169: t = build_ptr_desc (tdecl, type); ! 1170: } ! 1171: } ! 1172: else if (TYPE_BUILT_IN (type)) ! 1173: t = build_bltn_desc (tdecl, type); ! 1174: else if (IS_AGGR_TYPE (type)) ! 1175: { ! 1176: if (TYPE_PTRMEMFUNC_P (type)) ! 1177: { ! 1178: t = build_ptmf_desc (tdecl, type); ! 1179: } ! 1180: else ! 1181: { ! 1182: t = build_class_desc (tdecl, type); ! 1183: } ! 1184: } ! 1185: else if (TREE_CODE (type) == FUNCTION_TYPE) ! 1186: t = build_func_desc (tdecl); ! 1187: else ! 1188: t = build_user_desc (tdecl); ! 1189: ! 1190: pop_obstacks (); ! 1191: return t; ! 1192: } ! 1193: ! 1194: #if 0 ! 1195: /* This is the old dossier type descriptor generation code, it's much ! 1196: more extended than rtti. It's reserved for later use. */ 1.1 root 1197: /* Build an initializer for a __t_desc node. So that we can take advantage 1198: of recursion, we accept NULL for TYPE. 1199: DEFINITION is greater than zero iff we must define the type descriptor 1200: (as opposed to merely referencing it). 1 means treat according to 1201: #pragma interface/#pragma implementation rules. 2 means define as 1202: global and public, no matter what. */ 1203: tree 1204: build_t_desc (type, definition) 1205: tree type; 1206: int definition; 1207: { 1208: tree tdecl; 1209: tree tname, name_string; 1210: tree elems, fields; 1211: tree parents, vbases, offsets, ivars, methods, target_type; 1212: int method_count = 0, field_count = 0; 1213: 1214: if (type == NULL_TREE) 1215: return NULL_TREE; 1216: 1217: tname = build_t_desc_overload (type); 1218: if (IDENTIFIER_AS_DESC (tname) 1219: && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname)))) 1220: return IDENTIFIER_AS_DESC (tname); 1221: 1222: tdecl = lookup_name (tname, 0); 1223: if (tdecl == NULL_TREE) 1224: { 1225: tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node); 1226: DECL_EXTERNAL (tdecl) = 1; 1227: TREE_PUBLIC (tdecl) = 1; 1228: tdecl = pushdecl_top_level (tdecl); 1229: } 1230: /* If we previously defined it, return the defined result. */ 1231: else if (definition && DECL_INITIAL (tdecl)) 1232: return IDENTIFIER_AS_DESC (tname); 1233: 1234: if (definition) 1235: { 1236: tree taggr = type; 1237: /* Let T* and T& be written only when T is written (if T is an aggr). 1238: We do this for const, but not for volatile, since volatile 1239: is rare and const is not. */ 1240: if (!TYPE_VOLATILE (taggr) 1241: && (TREE_CODE (taggr) == POINTER_TYPE 1242: || TREE_CODE (taggr) == REFERENCE_TYPE) 1243: && IS_AGGR_TYPE (TREE_TYPE (taggr))) 1244: taggr = TREE_TYPE (taggr); 1245: 1246: /* If we know that we don't need to write out this type's 1247: vtable, then don't write out it's dossier. Somebody 1248: else will take care of that. */ 1249: if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr)) 1250: { 1251: if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr)) 1252: { 1253: TREE_PUBLIC (tdecl) = ! CLASSTYPE_INTERFACE_ONLY (taggr) 1254: && CLASSTYPE_INTERFACE_KNOWN (taggr); 1255: DECL_EXTERNAL (tdecl) = 0; 1256: } 1257: else 1258: { 1259: if (write_virtuals != 0) 1260: TREE_PUBLIC (tdecl) = 1; 1261: } 1262: } 1263: else 1264: { 1265: DECL_EXTERNAL (tdecl) = 0; 1266: TREE_PUBLIC (tdecl) = (definition > 1); 1267: } 1268: } 1269: SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0)); 1.1.1.2 ! root 1270: 1.1 root 1271: if (!definition || DECL_EXTERNAL (tdecl)) 1272: { 1273: /* That's it! */ 1.1.1.2 ! root 1274: cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0); 1.1 root 1275: return IDENTIFIER_AS_DESC (tname); 1276: } 1277: 1278: /* Show that we are defining the t_desc for this type. */ 1279: DECL_INITIAL (tdecl) = error_mark_node; 1280: 1281: parents = build_tree_list (NULL_TREE, integer_zero_node); 1282: vbases = build_tree_list (NULL_TREE, integer_zero_node); 1283: offsets = build_tree_list (NULL_TREE, integer_zero_node); 1284: methods = NULL_TREE; 1285: ivars = NULL_TREE; 1286: 1287: if (TYPE_LANG_SPECIFIC (type)) 1288: { 1289: int i = CLASSTYPE_N_BASECLASSES (type); 1290: tree method_vec = CLASSTYPE_METHOD_VEC (type); 1291: tree *meth, *end; 1292: tree binfos = TYPE_BINFO_BASETYPES (type); 1293: tree vb = CLASSTYPE_VBASECLASSES (type); 1294: 1295: while (--i >= 0) 1296: parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents); 1297: 1298: while (vb) 1299: { 1300: vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases); 1301: offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets); 1302: vb = TREE_CHAIN (vb); 1303: } 1304: 1305: if (method_vec) 1306: for (meth = TREE_VEC_END (method_vec), 1307: end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; ) 1308: if (*meth) 1309: { 1310: methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods); 1311: method_count++; 1312: } 1313: } 1314: 1315: if (IS_AGGR_TYPE (type)) 1316: { 1317: for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) 1318: if (TREE_CODE (fields) == FIELD_DECL 1319: || TREE_CODE (fields) == VAR_DECL) 1320: { 1321: ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars); 1322: field_count++; 1323: } 1324: ivars = nreverse (ivars); 1325: } 1326: 1.1.1.2 ! root 1327: parents = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), parents, 0); ! 1328: vbases = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), vbases, 0); ! 1329: offsets = finish_table (NULL_TREE, integer_type_node, offsets, 0); 1.1 root 1330: if (methods == NULL_TREE) 1331: methods = null_pointer_node; 1332: else 1333: methods = build_unary_op (ADDR_EXPR, 1.1.1.2 ! root 1334: finish_table (NULL_TREE, __m_desc_type_node, methods, 0), 1.1 root 1335: 0); 1336: if (ivars == NULL_TREE) 1337: ivars = null_pointer_node; 1338: else 1339: ivars = build_unary_op (ADDR_EXPR, 1.1.1.2 ! root 1340: finish_table (NULL_TREE, __i_desc_type_node, ivars, 0), 1.1 root 1341: 0); 1342: if (TREE_TYPE (type)) 1343: target_type = build_t_desc (TREE_TYPE (type), definition); 1344: else 1345: target_type = integer_zero_node; 1346: 1347: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname))); 1348: 1349: elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0), 1350: tree_cons (NULL_TREE, 1351: TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node, 1352: /* really should use bitfield initialization here. */ 1353: tree_cons (NULL_TREE, integer_zero_node, 1354: tree_cons (NULL_TREE, target_type, 1355: tree_cons (NULL_TREE, build_int_2 (field_count, 2), 1356: tree_cons (NULL_TREE, build_int_2 (method_count, 2), 1357: tree_cons (NULL_TREE, ivars, 1358: tree_cons (NULL_TREE, methods, 1359: tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0), 1360: tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0), 1361: build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0)))))))))))); 1362: return build_generic_desc (tdecl, elems); 1363: } 1364: 1365: /* Build an initializer for a __i_desc node. */ 1366: tree 1367: build_i_desc (decl) 1368: tree decl; 1369: { 1370: tree elems, name_string; 1371: tree taggr; 1372: 1373: name_string = DECL_NAME (decl); 1374: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string))); 1375: 1376: /* Now decide whether this ivar should cause it's type to get 1377: def'd or ref'd in this file. If the type we are looking at 1378: has a proxy definition, we look at the proxy (i.e., a 1379: `foo *' is equivalent to a `foo'). */ 1380: taggr = TREE_TYPE (decl); 1381: 1382: if ((TREE_CODE (taggr) == POINTER_TYPE 1383: || TREE_CODE (taggr) == REFERENCE_TYPE) 1384: && TYPE_VOLATILE (taggr) == 0) 1385: taggr = TREE_TYPE (taggr); 1386: 1387: elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0), 1388: tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl), 1389: build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl), 1390: ! IS_AGGR_TYPE (taggr))))); 1391: taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems); 1392: TREE_CONSTANT (taggr) = 1; 1393: TREE_STATIC (taggr) = 1; 1394: TREE_READONLY (taggr) = 1; 1395: return taggr; 1396: } 1397: 1398: /* Build an initializer for a __m_desc node. */ 1399: tree 1400: build_m_desc (decl) 1401: tree decl; 1402: { 1403: tree taggr, elems, name_string; 1404: tree parm_count, req_count, vindex, vcontext; 1405: tree parms; 1406: int p_count, r_count; 1407: tree parm_types = NULL_TREE; 1408: 1409: for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0; 1410: parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++) 1411: { 1412: taggr = TREE_VALUE (parms); 1413: if ((TREE_CODE (taggr) == POINTER_TYPE 1414: || TREE_CODE (taggr) == REFERENCE_TYPE) 1415: && TYPE_VOLATILE (taggr) == 0) 1416: taggr = TREE_TYPE (taggr); 1417: 1418: parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms), 1419: ! IS_AGGR_TYPE (taggr)), 1420: parm_types); 1421: if (TREE_PURPOSE (parms) == NULL_TREE) 1422: r_count++; 1423: } 1424: 1.1.1.2 ! root 1425: parm_types = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), 1.1 root 1426: nreverse (parm_types), 0); 1427: parm_count = build_int_2 (p_count, 0); 1428: req_count = build_int_2 (r_count, 0); 1429: 1430: if (DECL_VINDEX (decl)) 1431: vindex = DECL_VINDEX (decl); 1432: else 1433: vindex = integer_zero_node; 1434: if (DECL_CONTEXT (decl) 1435: && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't') 1436: vcontext = build_t_desc (DECL_CONTEXT (decl), 0); 1437: else 1438: vcontext = integer_zero_node; 1439: name_string = DECL_NAME (decl); 1440: if (name_string == NULL) 1441: name_string = DECL_ASSEMBLER_NAME (decl); 1442: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string))); 1443: 1444: /* Now decide whether the return type of this mvar 1445: should cause it's type to get def'd or ref'd in this file. 1446: If the type we are looking at has a proxy definition, 1447: we look at the proxy (i.e., a `foo *' is equivalent to a `foo'). */ 1448: taggr = TREE_TYPE (TREE_TYPE (decl)); 1449: 1450: if ((TREE_CODE (taggr) == POINTER_TYPE 1451: || TREE_CODE (taggr) == REFERENCE_TYPE) 1452: && TYPE_VOLATILE (taggr) == 0) 1453: taggr = TREE_TYPE (taggr); 1454: 1455: elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0), 1456: tree_cons (NULL_TREE, vindex, 1457: tree_cons (NULL_TREE, vcontext, 1458: tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)), 1459: ! IS_AGGR_TYPE (taggr)), 1.1.1.2 ! root 1460: tree_cons (NULL_TREE, build_c_cast (build_pointer_type (default_function_type), build_unary_op (ADDR_EXPR, decl, 0), 0), 1.1 root 1461: tree_cons (NULL_TREE, parm_count, 1462: tree_cons (NULL_TREE, req_count, 1463: build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0))))))))); 1464: 1465: taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems); 1466: TREE_CONSTANT (taggr) = 1; 1467: TREE_STATIC (taggr) = 1; 1468: TREE_READONLY (taggr) = 1; 1469: return taggr; 1470: } 1.1.1.2 ! root 1471: #endif /* dossier */ ! 1472: 1.1 root 1473: 1474: /* Conditionally emit code to set up an unwind-protect for the 1475: garbage collector. If this function doesn't do anything that involves 1476: the garbage collector, then do nothing. Otherwise, call __gc_push 1477: at the beginning and __gc_pop at the end. 1478: 1479: NOTE! The __gc_pop function must operate transparently, since 1480: it comes where the logical return label lies. This means that 1481: at runtime *it* must preserve any return value registers. */ 1482: 1483: void 1484: expand_gc_prologue_and_epilogue () 1485: { 1486: extern tree maybe_gc_cleanup; 1487: struct rtx_def *last_parm_insn, *mark; 1488: extern struct rtx_def *get_last_insn (); 1489: extern struct rtx_def *get_first_nonparm_insn (); 1490: extern struct rtx_def *previous_insn (); 1491: tree action; 1492: 1493: /* If we didn't need the obstack, don't cons any space. */ 1494: if (current_function_obstack_index == 0 1495: || current_function_obstack_usage == 0) 1496: return; 1497: 1498: mark = get_last_insn (); 1499: last_parm_insn = get_first_nonparm_insn (); 1500: if (last_parm_insn == 0) last_parm_insn = mark; 1501: else last_parm_insn = previous_insn (last_parm_insn); 1502: 1503: action = build_function_call (gc_push_fndecl, 1504: build_tree_list (NULL_TREE, size_int (++current_function_obstack_index))); 1505: expand_expr_stmt (action); 1506: 1507: reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn); 1508: 1509: /* This will be expanded as a cleanup. */ 1510: TREE_VALUE (maybe_gc_cleanup) 1511: = build_function_call (gc_pop_fndecl, NULL_TREE); 1512: } 1513: 1514: /* Some day we'll use this function as a call-back and clean 1515: up all the unnecessary gc dribble that we otherwise create. */ 1516: void 1517: lang_expand_end_bindings (first, last) 1518: struct rtx_def *first, *last; 1519: { 1520: } 1521: 1522: void 1523: init_gc_processing () 1524: { 1525: tree parmtypes = hash_tree_chain (class_star_type_node, 1526: hash_tree_chain (integer_type_node, NULL_TREE)); 1527: gc_protect_fndecl = define_function ("__gc_protect", 1528: build_function_type (class_star_type_node, parmtypes), 1529: NOT_BUILT_IN, 0, 0); 1530: 1531: parmtypes = hash_tree_chain (integer_type_node, NULL_TREE); 1532: gc_unprotect_fndecl = define_function ("__gc_unprotect", 1533: build_function_type (void_type_node, parmtypes), 1534: NOT_BUILT_IN, 0, 0); 1535: 1536: gc_push_fndecl = define_function ("__gc_push", 1537: TREE_TYPE (gc_unprotect_fndecl), 1538: NOT_BUILT_IN, 0, 0); 1539: 1540: gc_pop_fndecl = define_function ("__gc_pop", 1541: build_function_type (void_type_node, 1542: void_list_node), 1543: NOT_BUILT_IN, 0, 0); 1544: gc_nonobject = build_int_2 (0x80000000, 0); 1545: gc_visible = build_int_2 (0x40000000, 0); 1546: gc_white = integer_zero_node; 1547: gc_offwhite = build_int_2 (0x10000000, 0); 1548: gc_grey = build_int_2 (0x20000000, 0); 1549: gc_black = build_int_2 (0x30000000, 0); 1550: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.