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
This commit is contained in:
parent
94e091c833
commit
4a8d0c9c68
@ -1,3 +1,14 @@
|
||||
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
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
__asm__ __volatile__ (".vtable_entry %c0, %c1"
|
||||
: : "s"(&class_vtable),
|
||||
"i"((long)&vtbl[idx].pfn - (long)&vtbl[0])); */
|
||||
|
||||
static void
|
||||
build_vtable_entry_ref (basetype, idx)
|
||||
tree basetype, idx;
|
||||
static tree
|
||||
build_vtable_entry_ref (array_ref, instance, idx)
|
||||
tree array_ref, instance, 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);
|
||||
tree i, i2, vtable, first_fn, basetype;
|
||||
|
||||
s = build_unary_op (ADDR_EXPR, vtable, 0);
|
||||
s = build_tree_list (build_string (1, "s"), s);
|
||||
basetype = TREE_TYPE (instance);
|
||||
if (TREE_CODE (basetype) == REFERENCE_TYPE)
|
||||
basetype = TREE_TYPE (basetype);
|
||||
|
||||
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);
|
||||
vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
|
||||
first_fn = TYPE_BINFO_VTABLE (basetype);
|
||||
|
||||
finish_asm_stmt (ridpointers[RID_VOLATILE],
|
||||
build_string (sizeof(asm_stmt)-1, asm_stmt),
|
||||
NULL_TREE, chainon (s, i), NULL_TREE);
|
||||
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));
|
||||
|
||||
if (TREE_CODE (i) != INTEGER_CST)
|
||||
abort ();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
37
gcc/expr.c
37
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. */
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 *));
|
||||
|
@ -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"
|
||||
};
|
||||
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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).
|
||||
|
29
gcc/varasm.c
29
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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user