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.
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;
+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.
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));
\f
/* 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
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;
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. */
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;
}
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
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. */
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. */
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))
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;
}
}
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 *));
"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"
};
\f
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. */
+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.
// Build don't link:
-// Special g++ Options: -fvtable-gc
+// Special g++ Options: -fvtable-gc -S
// Origin: Mark Mitchell <mitchell@codesourcery.com>
struct S {
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).
(flags & SECTION_CODE ? "discard" : "same_size"));
}
}
+\f
+/* 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);
+}