Commit 4a8d0c9c by Richard Henderson Committed by Richard Henderson

rtl.h (REG_VTABLE_REF): New.

        * 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.
cp/
        * 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.
testsuite/
        * g++.old-deja/g++.other/crash18.C: Add -S to options.

From-SVN: r46195
parent 94e091c8
2001-10-11 Richard Henderson <rth@redhat.com> 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 * dwarf2out.c (rtl_for_decl_location): If no DECL_RTL, look
for a DECL_INITIAL. for a DECL_INITIAL.
......
...@@ -11952,6 +11952,12 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1) ...@@ -11952,6 +11952,12 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
place = i3; place = i3;
break; 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: case REG_NON_LOCAL_GOTO:
if (GET_CODE (i3) == JUMP_INSN) if (GET_CODE (i3) == JUMP_INSN)
place = i3; place = i3;
......
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> 2001-10-10 Richard Henderson <rth@redhat.com>
* parse.y (asm_operand): Allow named operands. * parse.y (asm_operand): Allow named operands.
......
...@@ -134,7 +134,8 @@ static tree add_implicitly_declared_members PARAMS ((tree, int, int, int)); ...@@ -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 fixed_type_or_null PARAMS ((tree, int *, int *));
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int, static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
int, int, tree)); 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 tree build_vtbl_initializer PARAMS ((tree, tree, tree, tree, int *));
static int count_fields PARAMS ((tree)); static int count_fields PARAMS ((tree));
static int add_fields_to_vec PARAMS ((tree, tree, int)); static int add_fields_to_vec PARAMS ((tree, tree, int));
...@@ -424,38 +425,31 @@ build_vbase_path (code, type, expr, path, nonnull) ...@@ -424,38 +425,31 @@ build_vbase_path (code, type, expr, path, nonnull)
/* Virtual function things. */ /* Virtual function things. */
/* We want to give the assembler the vtable identifier as well as static tree
the offset to the function pointer. So we generate 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" basetype = TREE_TYPE (instance);
: : "s"(&class_vtable), if (TREE_CODE (basetype) == REFERENCE_TYPE)
"i"((long)&vtbl[idx].pfn - (long)&vtbl[0])); */ basetype = TREE_TYPE (basetype);
static void vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
build_vtable_entry_ref (basetype, idx) first_fn = TYPE_BINFO_VTABLE (basetype);
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);
s = build_unary_op (ADDR_EXPR, vtable, 0); i = fold (build_array_ref (first_fn, idx));
s = build_tree_list (build_string (1, "s"), s); 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); if (TREE_CODE (i) != INTEGER_CST)
/* We must not convert to ptrdiff_type node here, since this could widen abort ();
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);
finish_asm_stmt (ridpointers[RID_VOLATILE], return build (VTABLE_REF, TREE_TYPE (array_ref), array_ref, vtable, i);
build_string (sizeof(asm_stmt)-1, asm_stmt),
NULL_TREE, chainon (s, i), NULL_TREE);
} }
/* Given an object INSTANCE, return an expression which yields the /* Given an object INSTANCE, return an expression which yields the
...@@ -463,8 +457,8 @@ build_vtable_entry_ref (basetype, idx) ...@@ -463,8 +457,8 @@ build_vtable_entry_ref (basetype, idx)
cases for INSTANCE which we take care of here, mainly to avoid cases for INSTANCE which we take care of here, mainly to avoid
creating extra tree nodes when we don't have to. */ creating extra tree nodes when we don't have to. */
tree static tree
build_vtbl_ref (instance, idx) build_vtbl_ref_1 (instance, idx)
tree instance, idx; tree instance, idx;
{ {
tree vtbl, aref; tree vtbl, aref;
...@@ -535,14 +529,23 @@ build_vtbl_ref (instance, idx) ...@@ -535,14 +529,23 @@ build_vtbl_ref (instance, idx)
assemble_external (vtbl); assemble_external (vtbl);
if (flag_vtable_gc)
build_vtable_entry_ref (basetype, idx);
aref = build_array_ref (vtbl, idx); aref = build_array_ref (vtbl, idx);
return aref; 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 /* Given an object INSTANCE, return an expression which yields a
function pointer corresponding to vtable element INDEX. */ function pointer corresponding to vtable element INDEX. */
...@@ -550,14 +553,17 @@ tree ...@@ -550,14 +553,17 @@ tree
build_vfn_ref (instance, idx) build_vfn_ref (instance, idx)
tree 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 /* When using function descriptors, the address of the
vtable entry is treated as a function pointer. */ vtable entry is treated as a function pointer. */
if (TARGET_VTABLE_USES_DESCRIPTORS) 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)); build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1));
if (flag_vtable_gc)
aref = build_vtable_entry_ref (aref, instance, idx);
return aref; return aref;
} }
......
...@@ -2406,23 +2406,23 @@ output_vtable_inherit (vars) ...@@ -2406,23 +2406,23 @@ output_vtable_inherit (vars)
tree vars; tree vars;
{ {
tree parent; 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); parent = binfo_for_vtable (vars);
if (parent == TYPE_BINFO (DECL_CONTEXT (vars))) if (parent == TYPE_BINFO (DECL_CONTEXT (vars)))
op[1] = const0_rtx; parent_rtx = const0_rtx;
else if (parent) else if (parent)
{ {
parent = get_vtbl_decl_for_binfo (TYPE_BINFO (BINFO_TYPE (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 else
my_friendly_abort (980826); my_friendly_abort (980826);
output_asm_insn (".vtable_inherit %c0, %c1", op); assemble_vtable_inherit (child_rtx, parent_rtx);
} }
static int static int
......
...@@ -7211,6 +7211,43 @@ expand_expr (exp, target, tmode, modifier) ...@@ -7211,6 +7211,43 @@ expand_expr (exp, target, tmode, modifier)
return target; 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. /* 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 But it's not certain that a special tree code will really be
necessary for these. INDIRECT_REF might work for them. */ necessary for these. INDIRECT_REF might work for them. */
......
...@@ -2375,9 +2375,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) ...@@ -2375,9 +2375,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
rtx body = PATTERN (insn); rtx body = PATTERN (insn);
int insn_code_number; int insn_code_number;
const char *template; const char *template;
#ifdef HAVE_cc0
rtx note; rtx note;
#endif
/* An INSN, JUMP_INSN or CALL_INSN. /* An INSN, JUMP_INSN or CALL_INSN.
First check for special kinds that recog doesn't recognize. */ First check for special kinds that recog doesn't recognize. */
...@@ -2799,7 +2797,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) ...@@ -2799,7 +2797,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (next != 0 && next != NEXT_INSN (insn)) if (next != 0 && next != NEXT_INSN (insn))
{ {
rtx prev = PREV_INSN (insn); rtx prev = PREV_INSN (insn);
rtx note;
for (note = NEXT_INSN (insn); note != next; for (note = NEXT_INSN (insn); note != next;
note = NEXT_INSN (note)) note = NEXT_INSN (note))
...@@ -2953,6 +2950,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) ...@@ -2953,6 +2950,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
INSN_DELETED_P (insn) = 1; INSN_DELETED_P (insn) = 1;
#endif #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; current_output_insn = debug_insn = 0;
} }
} }
......
...@@ -497,3 +497,8 @@ extern void default_named_section_asm_out_constructor PARAMS ((struct rtx_def *, ...@@ -497,3 +497,8 @@ extern void default_named_section_asm_out_constructor PARAMS ((struct rtx_def *,
int)); int));
extern void default_ctor_section_asm_out_constructor PARAMS ((struct rtx_def *, extern void default_ctor_section_asm_out_constructor PARAMS ((struct rtx_def *,
int)); 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 *));
...@@ -281,7 +281,8 @@ const char * const reg_note_name[] = ...@@ -281,7 +281,8 @@ const char * const reg_note_name[] =
"REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED", "REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED",
"REG_FRAME_RELATED_EXPR", "REG_EH_CONTEXT", "REG_EH_REGION", "REG_FRAME_RELATED_EXPR", "REG_EH_CONTEXT", "REG_EH_REGION",
"REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN", "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"
}; };
......
...@@ -579,7 +579,11 @@ enum reg_note ...@@ -579,7 +579,11 @@ enum reg_note
REG_SETJMP, REG_SETJMP,
/* Indicate calls that always returns. */ /* 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. */ /* The base value for branch probability notes. */
......
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> 2001-10-10 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
* gcc.c-torture/compile/20011010-1.c: New. * gcc.c-torture/compile/20011010-1.c: New.
......
// Build don't link: // Build don't link:
// Special g++ Options: -fvtable-gc // Special g++ Options: -fvtable-gc -S
// Origin: Mark Mitchell <mitchell@codesourcery.com> // Origin: Mark Mitchell <mitchell@codesourcery.com>
struct S { struct S {
......
...@@ -374,6 +374,13 @@ DEFTREECODE (ARRAY_REF, "array_ref", 'r', 2) ...@@ -374,6 +374,13 @@ DEFTREECODE (ARRAY_REF, "array_ref", 'r', 2)
of the range is taken from the type of the expression. */ of the range is taken from the type of the expression. */
DEFTREECODE (ARRAY_RANGE_REF, "array_range_ref", 'r', 2) 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. /* Constructor: return an aggregate value made from specified components.
In C, this is used only for structure and array initializers. In C, this is used only for structure and array initializers.
Also used for SET_TYPE in Chill (and potentially Pascal). Also used for SET_TYPE in Chill (and potentially Pascal).
......
...@@ -5297,3 +5297,32 @@ default_pe_asm_named_section (name, flags) ...@@ -5297,3 +5297,32 @@ default_pe_asm_named_section (name, flags)
(flags & SECTION_CODE ? "discard" : "same_size")); (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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment