diff options
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/combine.c | 6 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/class.c | 76 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 10 | ||||
-rw-r--r-- | gcc/expr.c | 37 | ||||
-rw-r--r-- | gcc/final.c | 9 | ||||
-rw-r--r-- | gcc/output.h | 5 | ||||
-rw-r--r-- | gcc/rtl.c | 3 | ||||
-rw-r--r-- | gcc/rtl.h | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/crash18.C | 2 | ||||
-rw-r--r-- | gcc/tree.def | 7 | ||||
-rw-r--r-- | gcc/varasm.c | 29 |
14 files changed, 168 insertions, 46 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7d8a498ee75..7c751673c35 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,16 @@ 2001-10-11 Richard Henderson <rth@redhat.com> + * rtl.h (REG_VTABLE_REF): New. + * rtl.c (reg_note_name): Add it. + * combine.c (distribute_notes): Handle it. + * final.c (final_scan_insn): Handle it. + * tree.def (VTABLE_REF): New. + * expr.c (expand_expr): Handle it. + * varasm.c (assemble_vtable_entry, assemble_vtable_inherit): New. + * output.h: Declare them. + +2001-10-11 Richard Henderson <rth@redhat.com> + * dwarf2out.c (rtl_for_decl_location): If no DECL_RTL, look for a DECL_INITIAL. diff --git a/gcc/combine.c b/gcc/combine.c index 12225db3c12..e16cb4d7d03 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -11952,6 +11952,12 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) place = i3; break; + case REG_VTABLE_REF: + /* ??? Should remain with *a particular* memory load. Given the + nature of vtable data, the last insn seems relatively safe. */ + place = i3; + break; + case REG_NON_LOCAL_GOTO: if (GET_CODE (i3) == JUMP_INSN) place = i3; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8d867bbd579..06806fc40f2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2001-10-11 Richard Henderson <rth@redhat.com> + + * class.c (build_vtable_entry_ref): Create a VTABLE_REF instead + of an asm statement. + (build_vtbl_ref_1): Split out from build_vtbl_ref. + (build_vfn_ref): Use it to handle vtable descriptors before + calling build_vtable_entry_ref. + * decl2.c (output_vtable_inherit): Use assemble_vtable_inherit. + 2001-10-10 Richard Henderson <rth@redhat.com> * parse.y (asm_operand): Allow named operands. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 97a35974102..305bde1d7fb 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -134,7 +134,8 @@ static tree add_implicitly_declared_members PARAMS ((tree, int, int, int)); static tree fixed_type_or_null PARAMS ((tree, int *, int *)); static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int, int, int, tree)); -static void build_vtable_entry_ref PARAMS ((tree, tree)); +static tree build_vtable_entry_ref PARAMS ((tree, tree, tree)); +static tree build_vtbl_ref_1 PARAMS ((tree, tree)); static tree build_vtbl_initializer PARAMS ((tree, tree, tree, tree, int *)); static int count_fields PARAMS ((tree)); static int add_fields_to_vec PARAMS ((tree, tree, int)); @@ -424,38 +425,31 @@ build_vbase_path (code, type, expr, path, nonnull) /* Virtual function things. */ -/* We want to give the assembler the vtable identifier as well as - the offset to the function pointer. So we generate +static tree +build_vtable_entry_ref (array_ref, instance, idx) + tree array_ref, instance, idx; +{ + tree i, i2, vtable, first_fn, basetype; - __asm__ __volatile__ (".vtable_entry %c0, %c1" - : : "s"(&class_vtable), - "i"((long)&vtbl[idx].pfn - (long)&vtbl[0])); */ + basetype = TREE_TYPE (instance); + if (TREE_CODE (basetype) == REFERENCE_TYPE) + basetype = TREE_TYPE (basetype); -static void -build_vtable_entry_ref (basetype, idx) - tree basetype, idx; -{ - static const char asm_stmt[] = ".vtable_entry %c0, %c1"; - tree s, i, i2; - tree vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype)); - tree first_fn = TYPE_BINFO_VTABLE (basetype); + vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype)); + first_fn = TYPE_BINFO_VTABLE (basetype); - s = build_unary_op (ADDR_EXPR, vtable, 0); - s = build_tree_list (build_string (1, "s"), s); + i = fold (build_array_ref (first_fn, idx)); + i = fold (build_c_cast (ptrdiff_type_node, + build_unary_op (ADDR_EXPR, i, 0))); + i2 = fold (build_array_ref (vtable, build_int_2 (0,0))); + i2 = fold (build_c_cast (ptrdiff_type_node, + build_unary_op (ADDR_EXPR, i2, 0))); + i = fold (cp_build_binary_op (MINUS_EXPR, i, i2)); - i = build_array_ref (first_fn, idx); - /* We must not convert to ptrdiff_type node here, since this could widen - from a partial to an integral node, which would create a - convert_expression that would be in the way of any simplifications. */ - i = build_c_cast (string_type_node, build_unary_op (ADDR_EXPR, i, 0)); - i2 = build_array_ref (vtable, build_int_2 (0,0)); - i2 = build_c_cast (string_type_node, build_unary_op (ADDR_EXPR, i2, 0)); - i = cp_build_binary_op (MINUS_EXPR, i, i2); - i = build_tree_list (build_string (1, "i"), i); + if (TREE_CODE (i) != INTEGER_CST) + abort (); - finish_asm_stmt (ridpointers[RID_VOLATILE], - build_string (sizeof(asm_stmt)-1, asm_stmt), - NULL_TREE, chainon (s, i), NULL_TREE); + return build (VTABLE_REF, TREE_TYPE (array_ref), array_ref, vtable, i); } /* Given an object INSTANCE, return an expression which yields the @@ -463,8 +457,8 @@ build_vtable_entry_ref (basetype, idx) cases for INSTANCE which we take care of here, mainly to avoid creating extra tree nodes when we don't have to. */ -tree -build_vtbl_ref (instance, idx) +static tree +build_vtbl_ref_1 (instance, idx) tree instance, idx; { tree vtbl, aref; @@ -535,14 +529,23 @@ build_vtbl_ref (instance, idx) assemble_external (vtbl); - if (flag_vtable_gc) - build_vtable_entry_ref (basetype, idx); - aref = build_array_ref (vtbl, idx); return aref; } +tree +build_vtbl_ref (instance, idx) + tree instance, idx; +{ + tree aref = build_vtbl_ref_1 (instance, idx); + + if (flag_vtable_gc) + aref = build_vtable_entry_ref (aref, instance, idx); + + return aref; +} + /* Given an object INSTANCE, return an expression which yields a function pointer corresponding to vtable element INDEX. */ @@ -550,14 +553,17 @@ tree build_vfn_ref (instance, idx) tree instance, idx; { - tree aref = build_vtbl_ref (instance, idx); + tree aref = build_vtbl_ref_1 (instance, idx); /* When using function descriptors, the address of the vtable entry is treated as a function pointer. */ if (TARGET_VTABLE_USES_DESCRIPTORS) - return build1 (NOP_EXPR, TREE_TYPE (aref), + aref = build1 (NOP_EXPR, TREE_TYPE (aref), build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1)); + if (flag_vtable_gc) + aref = build_vtable_entry_ref (aref, instance, idx); + return aref; } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0ab9299244e..8c5dba17507 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2406,23 +2406,23 @@ output_vtable_inherit (vars) tree vars; { tree parent; - rtx op[2]; + rtx child_rtx, parent_rtx; - op[0] = XEXP (DECL_RTL (vars), 0); /* strip the mem ref */ + child_rtx = XEXP (DECL_RTL (vars), 0); /* strip the mem ref */ parent = binfo_for_vtable (vars); if (parent == TYPE_BINFO (DECL_CONTEXT (vars))) - op[1] = const0_rtx; + parent_rtx = const0_rtx; else if (parent) { parent = get_vtbl_decl_for_binfo (TYPE_BINFO (BINFO_TYPE (parent))); - op[1] = XEXP (DECL_RTL (parent), 0); /* strip the mem ref */ + parent_rtx = XEXP (DECL_RTL (parent), 0); /* strip the mem ref */ } else my_friendly_abort (980826); - output_asm_insn (".vtable_inherit %c0, %c1", op); + assemble_vtable_inherit (child_rtx, parent_rtx); } static int diff --git a/gcc/expr.c b/gcc/expr.c index 9457e8fd7be..1c81f73670e 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -7211,6 +7211,43 @@ expand_expr (exp, target, tmode, modifier) return target; } + case VTABLE_REF: + { + rtx insn, before = get_last_insn (), vtbl_ref; + + /* Evaluate the interior expression. */ + subtarget = expand_expr (TREE_OPERAND (exp, 0), target, + tmode, modifier); + + /* Get or create an instruction off which to hang a note. */ + if (REG_P (subtarget)) + { + target = subtarget; + insn = get_last_insn (); + if (insn == before) + abort (); + if (! INSN_P (insn)) + insn = prev_nonnote_insn (insn); + } + else + { + target = gen_reg_rtx (GET_MODE (subtarget)); + insn = emit_move_insn (target, subtarget); + } + + /* Collect the data for the note. */ + vtbl_ref = XEXP (DECL_RTL (TREE_OPERAND (exp, 1)), 0); + vtbl_ref = plus_constant (vtbl_ref, + tree_low_cst (TREE_OPERAND (exp, 2), 0)); + /* Discard the initial CONST that was added. */ + vtbl_ref = XEXP (vtbl_ref, 0); + + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_VTABLE_REF, vtbl_ref, REG_NOTES (insn)); + + return target; + } + /* Intended for a reference to a buffer of a file-object in Pascal. But it's not certain that a special tree code will really be necessary for these. INDIRECT_REF might work for them. */ diff --git a/gcc/final.c b/gcc/final.c index 28f756d1475..5884382b239 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -2375,9 +2375,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) rtx body = PATTERN (insn); int insn_code_number; const char *template; -#ifdef HAVE_cc0 rtx note; -#endif /* An INSN, JUMP_INSN or CALL_INSN. First check for special kinds that recog doesn't recognize. */ @@ -2799,7 +2797,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) if (next != 0 && next != NEXT_INSN (insn)) { rtx prev = PREV_INSN (insn); - rtx note; for (note = NEXT_INSN (insn); note != next; note = NEXT_INSN (note)) @@ -2953,6 +2950,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) INSN_DELETED_P (insn) = 1; #endif + /* Emit information for vtable gc. */ + note = find_reg_note (insn, REG_VTABLE_REF, NULL_RTX); + if (note) + assemble_vtable_entry (XEXP (XEXP (note, 0), 0), + INTVAL (XEXP (XEXP (note, 0), 1))); + current_output_insn = debug_insn = 0; } } diff --git a/gcc/output.h b/gcc/output.h index 9194aea4f2f..1e97c212536 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -497,3 +497,8 @@ extern void default_named_section_asm_out_constructor PARAMS ((struct rtx_def *, int)); extern void default_ctor_section_asm_out_constructor PARAMS ((struct rtx_def *, int)); + +/* Emit data for vtable gc for GNU binutils. */ +extern void assemble_vtable_entry PARAMS ((struct rtx_def *, HOST_WIDE_INT)); +extern void assemble_vtable_inherit PARAMS ((struct rtx_def *, + struct rtx_def *)); diff --git a/gcc/rtl.c b/gcc/rtl.c index bcf300522f4..7a07b7279c0 100644 --- a/gcc/rtl.c +++ b/gcc/rtl.c @@ -281,7 +281,8 @@ const char * const reg_note_name[] = "REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED", "REG_FRAME_RELATED_EXPR", "REG_EH_CONTEXT", "REG_EH_REGION", "REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN", - "REG_NON_LOCAL_GOTO", "REG_SETJMP", "REG_ALWAYS_RETURN" + "REG_NON_LOCAL_GOTO", "REG_SETJMP", "REG_ALWAYS_RETURN", + "REG_VTABLE_REF" }; diff --git a/gcc/rtl.h b/gcc/rtl.h index 37a204c95d6..4c0eb2c4e83 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -579,7 +579,11 @@ enum reg_note REG_SETJMP, /* Indicate calls that always returns. */ - REG_ALWAYS_RETURN + REG_ALWAYS_RETURN, + + /* Indicate that the memory load references a vtable. The expression + is of the form (plus (symbol_ref vtable_sym) (const_int offset)). */ + REG_VTABLE_REF }; /* The base value for branch probability notes. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index eb25dca9c91..d7fd68e6291 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-10-11 Richard Henderson <rth@redhat.com> + + * g++.old-deja/g++.other/crash18.C: Add -S to options. + 2001-10-10 Franz Sirl <Franz.Sirl-kernel@lauterbach.com> * gcc.c-torture/compile/20011010-1.c: New. diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash18.C b/gcc/testsuite/g++.old-deja/g++.other/crash18.C index 789e3166fb4..335d8b91d19 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/crash18.C +++ b/gcc/testsuite/g++.old-deja/g++.other/crash18.C @@ -1,5 +1,5 @@ // Build don't link: -// Special g++ Options: -fvtable-gc +// Special g++ Options: -fvtable-gc -S // Origin: Mark Mitchell <mitchell@codesourcery.com> struct S { diff --git a/gcc/tree.def b/gcc/tree.def index 4b155b0796c..8a02e5b2f60 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -374,6 +374,13 @@ DEFTREECODE (ARRAY_REF, "array_ref", 'r', 2) of the range is taken from the type of the expression. */ DEFTREECODE (ARRAY_RANGE_REF, "array_range_ref", 'r', 2) +/* Vtable indexing. Carries data useful for emitting information + for vtable garbage collection. + Operand 0: an array_ref (or equivalent expression) + Operand 1: the vtable base (must be a var_decl) + Operand 2: index into vtable (must be an integer_cst). */ +DEFTREECODE (VTABLE_REF, "vtable_ref", 'r', 3) + /* Constructor: return an aggregate value made from specified components. In C, this is used only for structure and array initializers. Also used for SET_TYPE in Chill (and potentially Pascal). diff --git a/gcc/varasm.c b/gcc/varasm.c index 312387530bd..0d6dc76c3a3 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -5297,3 +5297,32 @@ default_pe_asm_named_section (name, flags) (flags & SECTION_CODE ? "discard" : "same_size")); } } + +/* Used for vtable gc in GNU binutils. Record that the pointer at OFFSET + from SYMBOL is used in all classes derived from SYMBOL. */ + +void +assemble_vtable_entry (symbol, offset) + rtx symbol; + HOST_WIDE_INT offset; +{ + fputs ("\t.vtable_entry ", asm_out_file); + output_addr_const (asm_out_file, symbol); + fputs (", ", asm_out_file); + fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, offset); + fputc ('\n', asm_out_file); +} + +/* Used for vtable gc in GNU binutils. Record the class heirarchy by noting + that the vtable symbol CHILD is derived from the vtable symbol PARENT. */ + +void +assemble_vtable_inherit (child, parent) + rtx child, parent; +{ + fputs ("\t.vtable_inherit ", asm_out_file); + output_addr_const (asm_out_file, child); + fputs (", ", asm_out_file); + output_addr_const (asm_out_file, parent); + fputc ('\n', asm_out_file); +} |