|
|
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: 419: /* Build and initialize various sorts of descriptors. Every descriptor 420: node has a name associated with it (the name created by mangling). 421: For this reason, we use the identifier as our access to the __*_desc 422: nodes, instead of sticking them directly in the types. Otherwise we 423: would burden all built-in types (and pointer types) with slots that 424: we don't necessarily want to use. 425: 426: For each descriptor we build, we build a variable that contains 427: the descriptor's information. When we need this info at runtime, 428: all we need is access to these variables. 429: 430: Note: these constructors always return the address of the descriptor 431: info, since that is simplest for their mutual interaction. */ 432: 433: static tree 434: build_generic_desc (decl, elems) 435: tree decl; 436: tree elems; 437: { 438: tree init = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE, elems); 439: TREE_CONSTANT (init) = 1; 440: TREE_STATIC (init) = 1; 441: TREE_READONLY (init) = 1; 442: 443: DECL_INITIAL (decl) = init; 444: TREE_STATIC (decl) = 1; 445: layout_decl (decl, 0); 446: finish_decl (decl, init, 0, 0); 447: 448: return IDENTIFIER_AS_DESC (DECL_NAME (decl)); 449: } 450: 451: /* Build an initializer for a __t_desc node. So that we can take advantage 452: of recursion, we accept NULL for TYPE. 453: DEFINITION is greater than zero iff we must define the type descriptor 454: (as opposed to merely referencing it). 1 means treat according to 455: #pragma interface/#pragma implementation rules. 2 means define as 456: global and public, no matter what. */ 457: tree 458: build_t_desc (type, definition) 459: tree type; 460: int definition; 461: { 462: tree tdecl; 463: tree tname, name_string; 464: tree elems, fields; 465: tree parents, vbases, offsets, ivars, methods, target_type; 466: int method_count = 0, field_count = 0; 467: 468: if (type == NULL_TREE) 469: return NULL_TREE; 470: 471: tname = build_t_desc_overload (type); 472: if (IDENTIFIER_AS_DESC (tname) 473: && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname)))) 474: return IDENTIFIER_AS_DESC (tname); 475: 476: tdecl = lookup_name (tname, 0); 477: if (tdecl == NULL_TREE) 478: { 479: tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node); 1.1.1.4 root 480: DECL_EXTERNAL (tdecl) = 1; 1.1 root 481: TREE_PUBLIC (tdecl) = 1; 482: tdecl = pushdecl_top_level (tdecl); 483: } 484: /* If we previously defined it, return the defined result. */ 485: else if (definition && DECL_INITIAL (tdecl)) 486: return IDENTIFIER_AS_DESC (tname); 487: 488: if (definition) 489: { 490: tree taggr = type; 491: /* Let T* and T& be written only when T is written (if T is an aggr). 492: We do this for const, but not for volatile, since volatile 493: is rare and const is not. */ 494: if (!TYPE_VOLATILE (taggr) 495: && (TREE_CODE (taggr) == POINTER_TYPE 496: || TREE_CODE (taggr) == REFERENCE_TYPE) 497: && IS_AGGR_TYPE (TREE_TYPE (taggr))) 498: taggr = TREE_TYPE (taggr); 499: 500: /* If we know that we don't need to write out this type's 501: vtable, then don't write out it's dossier. Somebody 502: else will take care of that. */ 503: if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr)) 504: { 505: if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr)) 506: { 507: TREE_PUBLIC (tdecl) = !(CLASSTYPE_INTERFACE_ONLY (taggr) 508: || CLASSTYPE_INTERFACE_UNKNOWN (taggr)); 509: TREE_STATIC (tdecl) = 1; 1.1.1.4 root 510: DECL_EXTERNAL (tdecl) = 0; 1.1 root 511: } 512: else 513: { 514: if (write_virtuals != 0) 515: TREE_PUBLIC (tdecl) = 1; 516: } 517: } 518: else 519: { 1.1.1.4 root 520: DECL_EXTERNAL (tdecl) = 0; 1.1 root 521: TREE_STATIC (tdecl) = 1; 522: TREE_PUBLIC (tdecl) = (definition > 1); 523: } 524: } 525: SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0)); 1.1.1.4 root 526: if (!definition || DECL_EXTERNAL (tdecl)) 1.1 root 527: { 528: /* That's it! */ 529: finish_decl (tdecl, 0, 0, 0); 530: return IDENTIFIER_AS_DESC (tname); 531: } 532: 533: /* Show that we are defining the t_desc for this type. */ 534: DECL_INITIAL (tdecl) = error_mark_node; 535: 536: parents = build_tree_list (NULL_TREE, integer_zero_node); 537: vbases = build_tree_list (NULL_TREE, integer_zero_node); 538: offsets = build_tree_list (NULL_TREE, integer_zero_node); 539: methods = NULL_TREE; 540: ivars = NULL_TREE; 541: 542: if (TYPE_LANG_SPECIFIC (type)) 543: { 544: int i = CLASSTYPE_N_BASECLASSES (type); 545: tree method_vec = CLASSTYPE_METHOD_VEC (type); 546: tree *meth, *end; 547: tree binfos = TYPE_BINFO_BASETYPES (type); 548: tree vb = CLASSTYPE_VBASECLASSES (type); 549: 550: while (--i >= 0) 551: parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents); 552: 553: while (vb) 554: { 555: vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases); 556: offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets); 557: vb = TREE_CHAIN (vb); 558: } 559: 560: if (method_vec) 561: for (meth = TREE_VEC_END (method_vec), 562: end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; ) 563: if (*meth) 564: { 565: methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods); 566: method_count++; 567: } 568: } 569: 570: if (IS_AGGR_TYPE (type)) 571: { 572: for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) 573: if (TREE_CODE (fields) == FIELD_DECL 574: || TREE_CODE (fields) == VAR_DECL) 575: { 576: ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars); 577: field_count++; 578: } 579: ivars = nreverse (ivars); 580: } 581: 582: parents = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), parents, 0); 583: vbases = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), vbases, 0); 584: offsets = finish_table (0, integer_type_node, offsets, 0); 585: methods = finish_table (0, __m_desc_type_node, methods, 0); 586: ivars = finish_table (0, __i_desc_type_node, ivars, 0); 587: if (TREE_TYPE (type)) 588: target_type = build_t_desc (TREE_TYPE (type), definition); 589: else 590: target_type = integer_zero_node; 591: 592: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname))); 593: 594: elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0), 595: tree_cons (NULL_TREE, 596: TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node, 597: /* really should use bitfield initialization here. */ 598: tree_cons (NULL_TREE, integer_zero_node, 599: tree_cons (NULL_TREE, target_type, 600: tree_cons (NULL_TREE, build_int_2 (field_count, 2), 601: tree_cons (NULL_TREE, build_int_2 (method_count, 2), 602: tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, ivars, 0), 603: tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, methods, 0), 604: tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0), 605: tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0), 606: build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0)))))))))))); 607: return build_generic_desc (tdecl, elems); 608: } 609: 610: /* Build an initializer for a __i_desc node. */ 611: tree 612: build_i_desc (decl) 613: tree decl; 614: { 615: tree elems, name_string; 616: tree taggr; 617: 618: name_string = DECL_NAME (decl); 619: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string))); 620: 621: /* Now decide whether this ivar should cause it's type to get 622: def'd or ref'd in this file. If the type we are looking at 623: has a proxy definition, we look at the proxy (i.e., a 624: `foo *' is equivalent to a `foo'). */ 625: taggr = TREE_TYPE (decl); 626: 627: if ((TREE_CODE (taggr) == POINTER_TYPE 628: || TREE_CODE (taggr) == REFERENCE_TYPE) 629: && TYPE_VOLATILE (taggr) == 0) 630: taggr = TREE_TYPE (taggr); 631: 632: elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0), 633: tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl), 634: build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl), 635: ! IS_AGGR_TYPE (taggr))))); 636: taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems); 637: TREE_CONSTANT (taggr) = 1; 638: TREE_STATIC (taggr) = 1; 639: TREE_READONLY (taggr) = 1; 640: return taggr; 641: } 642: 643: /* Build an initializer for a __m_desc node. */ 644: tree 645: build_m_desc (decl) 646: tree decl; 647: { 648: tree taggr, elems, name_string; 649: tree parm_count, req_count, vindex, vcontext; 650: tree parms; 651: int p_count, r_count; 652: tree parm_types = NULL_TREE; 653: 654: for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0; 655: parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++) 656: { 657: taggr = TREE_VALUE (parms); 658: if ((TREE_CODE (taggr) == POINTER_TYPE 659: || TREE_CODE (taggr) == REFERENCE_TYPE) 660: && TYPE_VOLATILE (taggr) == 0) 661: taggr = TREE_TYPE (taggr); 662: 663: parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms), 664: ! IS_AGGR_TYPE (taggr)), 665: parm_types); 666: if (TREE_PURPOSE (parms) == NULL_TREE) 667: r_count++; 668: } 669: 670: parm_types = finish_table (0, TYPE_POINTER_TO (__t_desc_type_node), 671: nreverse (parm_types), 0); 672: parm_count = build_int_2 (p_count, 0); 673: req_count = build_int_2 (r_count, 0); 674: 675: if (DECL_VINDEX (decl)) 676: vindex = DECL_VINDEX (decl); 677: else 678: vindex = integer_zero_node; 1.1.1.4 root 679: if (DECL_CONTEXT (decl) 680: && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't') 1.1 root 681: vcontext = build_t_desc (DECL_CONTEXT (decl), 0); 682: else 683: vcontext = integer_zero_node; 684: name_string = DECL_NAME (decl); 685: if (name_string == NULL) 686: name_string = DECL_ASSEMBLER_NAME (decl); 687: name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string))); 688: 689: /* Now decide whether the return type of this mvar 690: should cause it's type to get def'd or ref'd in this file. 691: If the type we are looking at has a proxy definition, 692: we look at the proxy (i.e., a `foo *' is equivalent to a `foo'). */ 693: taggr = TREE_TYPE (TREE_TYPE (decl)); 694: 695: if ((TREE_CODE (taggr) == POINTER_TYPE 696: || TREE_CODE (taggr) == REFERENCE_TYPE) 697: && TYPE_VOLATILE (taggr) == 0) 698: taggr = TREE_TYPE (taggr); 699: 700: elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0), 701: tree_cons (NULL_TREE, vindex, 702: tree_cons (NULL_TREE, vcontext, 703: tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)), 704: ! IS_AGGR_TYPE (taggr)), 705: tree_cons (NULL_TREE, build_c_cast (TYPE_POINTER_TO (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)), 706: tree_cons (NULL_TREE, parm_count, 707: tree_cons (NULL_TREE, req_count, 708: build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0))))))))); 709: 710: taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems); 711: TREE_CONSTANT (taggr) = 1; 712: TREE_STATIC (taggr) = 1; 713: TREE_READONLY (taggr) = 1; 714: return taggr; 715: } 716: 717: /* Conditionally emit code to set up an unwind-protect for the 718: garbage collector. If this function doesn't do anything that involves 719: the garbage collector, then do nothing. Otherwise, call __gc_push 720: at the beginning and __gc_pop at the end. 721: 722: NOTE! The __gc_pop function must operate transparently, since 723: it comes where the logical return label lies. This means that 724: at runtime *it* must preserve any return value registers. */ 725: 726: void 727: expand_gc_prologue_and_epilogue () 728: { 729: extern tree maybe_gc_cleanup; 730: struct rtx_def *last_parm_insn, *mark; 731: extern struct rtx_def *get_last_insn (); 732: extern struct rtx_def *get_first_nonparm_insn (); 733: extern struct rtx_def *previous_insn (); 734: tree action; 735: 736: /* If we didn't need the obstack, don't cons any space. */ 737: if (current_function_obstack_index == 0 738: || current_function_obstack_usage == 0) 739: return; 740: 741: mark = get_last_insn (); 742: last_parm_insn = get_first_nonparm_insn (); 743: if (last_parm_insn == 0) last_parm_insn = mark; 744: else last_parm_insn = previous_insn (last_parm_insn); 745: 746: action = build_function_call (gc_push_fndecl, 747: build_tree_list (NULL_TREE, size_int (++current_function_obstack_index))); 748: expand_expr_stmt (action); 749: 750: reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn); 751: 752: /* This will be expanded as a cleanup. */ 753: TREE_VALUE (maybe_gc_cleanup) 754: = build_function_call (gc_pop_fndecl, NULL_TREE); 755: } 756: 757: /* Some day we'll use this function as a call-back and clean 758: up all the unnecessary gc dribble that we otherwise create. */ 759: void 760: lang_expand_end_bindings (first, last) 761: struct rtx_def *first, *last; 762: { 763: } 764: 765: void 766: init_gc_processing () 767: { 768: tree parmtypes = hash_tree_chain (class_star_type_node, 769: hash_tree_chain (integer_type_node, NULL_TREE)); 770: gc_protect_fndecl = define_function ("__gc_protect", 771: build_function_type (class_star_type_node, parmtypes), 772: NOT_BUILT_IN, 0, 0); 773: 774: parmtypes = hash_tree_chain (integer_type_node, NULL_TREE); 775: gc_unprotect_fndecl = define_function ("__gc_unprotect", 776: build_function_type (void_type_node, parmtypes), 777: NOT_BUILT_IN, 0, 0); 778: 779: gc_push_fndecl = define_function ("__gc_push", 780: TREE_TYPE (gc_unprotect_fndecl), 781: NOT_BUILT_IN, 0, 0); 782: 783: gc_pop_fndecl = define_function ("__gc_pop", 784: build_function_type (void_type_node, 785: void_list_node), 786: NOT_BUILT_IN, 0, 0); 787: gc_nonobject = build_int_2 (0x80000000, 0); 788: gc_visible = build_int_2 (0x40000000, 0); 789: gc_white = integer_zero_node; 790: gc_offwhite = build_int_2 (0x10000000, 0); 791: gc_grey = build_int_2 (0x20000000, 0); 792: gc_black = build_int_2 (0x30000000, 0); 793: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.