[c++] -fvtable-gc reorg
Richard Henderson
rth@redhat.com
Tue Feb 13 14:58:00 GMT 2001
On Tue, Feb 13, 2001 at 03:07:20PM +0000, Jason Merrill wrote:
> It seems a bit odd to me that the VTABLE_REF wraps the CALL_EXPR rather
> than going inside, to express the load from the vtable.
Here's a revised patch to that effect. Ok?
r~
gcc/
* configure.in (HAVE_AS_VTABLE_GC): New. Detect support.
* final.c (final_scan_insn): Look for REG_VTABLE_ENTRY notes.
* varasm.c (asm_emit_vtable_inherit): New.
(asm_emit_vtable_entry): New.
* output.h: Declare them.
* rtl.h (REG_VTABLE_ENTRY): New.
* rtl.c (reg_note_name): Update.
gcc/cp/
* call.c (build_over_call): Create a VTABLE_REF node for
a virtual member call.
* class.c (build_vtable_entry_ref): Rewrite to emit
a REG_VTABLE_ENTRY note.
(build_vtbl_ref): Don't call build_vtable_entry_ref here.
* cp-tree.def (VTABLE_REF): New.
* cp-tree.h (build_vtable_entry_ref): Declare.
* decl2.c (output_vtable_inherit): Use asm_emit_vtable_inherit.
* expr.c (cplus_expand_expr): Handle VTABLE_REF.
* lex.c (cxx_post_options): Warn if -fvtable-gc not supported.
Index: gcc/configure.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/configure.in,v
retrieving revision 1.484
diff -c -p -d -r1.484 configure.in
*** configure.in 2001/02/13 13:00:04 1.484
--- configure.in 2001/02/13 22:55:20
*************** if test x"$gcc_cv_as_hidden" = xyes; the
*** 1302,1307 ****
--- 1302,1330 ----
fi
AC_MSG_RESULT($gcc_cv_as_hidden)
+ AC_MSG_CHECKING(assembler vtable gc support)
+ # ??? We really need to be able to run the assembler to make sure
+ # this will actually work for a cross target.
+ gcc_cv_as_vtable_gc=no
+ if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
+ if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 10 -o "$gcc_cv_gas_major_version" -gt 2; then
+ gcc_cv_as_vtable_gc="yes"
+ fi
+ elif test x$gcc_cv_as != x; then
+ # Check if we have .vtable_inherit and .vtable_entry
+ echo "foobar:" > conftest.s
+ echo " .vtable_inherit foobar, 0" >> conftest.s
+ echo " .vtable_entry foobar, 0" >> conftest.s
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_vtable_gc="yes"
+ fi
+ rm -f conftest.s conftest.o conftest.nm1 conftest.nm2
+ fi
+ if test x"$gcc_cv_as_vtable_gc" = xyes; then
+ AC_DEFINE(HAVE_AS_VTABLE_GC, 1, [Define if your assembler supports vtable gc directives.])
+ fi
+ AC_MSG_RESULT($gcc_cv_as_vtable_gc)
+
case "$target" in
sparc*-*-*)
AC_CACHE_CHECK([assembler .register pseudo-op support],
Index: gcc/final.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/final.c,v
retrieving revision 1.158
diff -c -p -d -r1.158 final.c
*** final.c 2001/02/08 15:09:05 1.158
--- final.c 2001/02/13 22:55:20
*************** final_scan_insn (insn, file, optimize, p
*** 2445,2459 ****
register 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 (GET_CODE (body) == USE /* These are just declarations */
! || GET_CODE (body) == CLOBBER)
break;
#ifdef HAVE_cc0
--- 2445,2460 ----
register rtx body = PATTERN (insn);
int insn_code_number;
const char *template;
rtx note;
! /* An INSN, JUMP_INSN or CALL_INSN. */
! note = find_reg_note (insn, REG_VTABLE_ENTRY, NULL_RTX);
! if (note)
! asm_emit_vtable_entry (XEXP (note, 0));
!
! /* Check for special kinds that recog doesn't recognize. */
! if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER)
break;
#ifdef HAVE_cc0
Index: gcc/output.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/output.h,v
retrieving revision 1.55
diff -c -p -d -r1.55 output.h
*** output.h 2001/02/07 01:04:36 1.55
--- output.h 2001/02/13 22:55:20
*************** extern tree initializer_constant_valid_p
*** 362,367 ****
--- 362,373 ----
extern void output_constant PARAMS ((tree, int));
#endif
+ #ifdef RTX_CODE
+ /* Support for vtable gc. */
+ extern void asm_emit_vtable_inherit PARAMS ((rtx, rtx));
+ extern void asm_emit_vtable_entry PARAMS ((rtx));
+ #endif
+
/* When outputting assembler code, indicates which alternative
of the constraints was actually satisfied. */
extern int which_alternative;
Index: gcc/rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.c,v
retrieving revision 1.86
diff -c -p -d -r1.86 rtl.c
*** rtl.c 2000/12/27 16:35:00 1.86
--- rtl.c 2001/02/13 22:55:20
*************** const char * const reg_note_name[] =
*** 289,295 ****
"REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED",
"REG_FRAME_RELATED_EXPR", "REG_EH_CONTEXT", "REG_EH_REGION",
"REG_EH_RETHROW", "REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN",
! "REG_NON_LOCAL_GOTO"
};
static htab_t md_constants;
--- 289,295 ----
"REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED",
"REG_FRAME_RELATED_EXPR", "REG_EH_CONTEXT", "REG_EH_REGION",
"REG_EH_RETHROW", "REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN",
! "REG_NON_LOCAL_GOTO", "REG_VTABLE_ENTRY"
};
static htab_t md_constants;
Index: gcc/rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.242
diff -c -p -d -r1.242 rtl.h
*** rtl.h 2001/02/13 20:43:13 1.242
--- rtl.h 2001/02/13 22:55:20
*************** enum reg_note
*** 554,560 ****
/* Indicates that an indirect jump is a non-local goto instead of a
computed goto. */
! REG_NON_LOCAL_GOTO
};
/* The base value for branch probability notes. */
--- 554,564 ----
/* Indicates that an indirect jump is a non-local goto instead of a
computed goto. */
! REG_NON_LOCAL_GOTO,
!
! /* Indicates a vtable reference. Used with -fvtable-gc. The operand
! is a PLUS of the vtable symbol and a byte offset. */
! REG_VTABLE_ENTRY
};
/* The base value for branch probability notes. */
Index: gcc/varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.161
diff -c -p -d -r1.161 varasm.c
*** varasm.c 2001/02/04 08:29:46 1.161
--- varasm.c 2001/02/13 22:55:21
*************** assemble_eh_integer (x, size, force)
*** 4948,4952 ****
--- 4948,4991 ----
return (assemble_integer (x, size, force));
}
+ /* Describe to the assembler the relationship between a vtable and the
+ vtable of the parent class. */
+
+ void
+ asm_emit_vtable_inherit (table, parent)
+ rtx table, parent;
+ {
+ #ifdef HAVE_AS_VTABLE_GC
+ /* We will have warned for the non-existance of this feature elsewhere. */
+ fputs ("\t.vtable_inherit ", asm_out_file);
+ output_addr_const (asm_out_file, table);
+ fputs (", ", asm_out_file);
+ output_addr_const (asm_out_file, parent);
+ fputc ('\n', asm_out_file);
+ #endif
+ }
+ /* Describe the use of a particular entry in a vtable. */
+ void
+ asm_emit_vtable_entry (ref)
+ rtx ref;
+ {
+ #ifdef HAVE_AS_VTABLE_GC
+ HOST_WIDE_INT offset = 0;
+
+ if (GET_CODE (ref) == PLUS)
+ {
+ offset = INTVAL (XEXP (ref, 1));
+ ref = XEXP (ref, 0);
+ }
+ if (GET_CODE (ref) != SYMBOL_REF)
+ abort ();
+
+ fputs ("\t.vtable_entry ", asm_out_file);
+ assemble_name (asm_out_file, XSTR (ref, 0));
+ fputs (", ", asm_out_file);
+ fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, offset);
+ fputc ('\n', asm_out_file);
+ #endif
+ }
Index: gcc/cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.255
diff -c -p -d -r1.255 call.c
*** call.c 2001/02/12 09:58:16 1.255
--- call.c 2001/02/13 22:55:21
*************** build_over_call (cand, args, flags)
*** 4254,4268 ****
if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
{
! tree t, *p = &TREE_VALUE (converted_args);
! tree binfo = get_binfo
! (DECL_VIRTUAL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0);
*p = convert_pointer_to_real (binfo, *p);
if (TREE_SIDE_EFFECTS (*p))
*p = save_expr (*p);
t = build_pointer_type (TREE_TYPE (fn));
! fn = build_vfn_ref (p, build_indirect_ref (*p, 0), DECL_VINDEX (fn));
TREE_TYPE (fn) = t;
}
else if (DECL_INLINE (fn))
fn = inline_conversion (fn);
--- 4254,4283 ----
if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
{
! tree t, *p, binfo, ref;
! tree vtbl_type, vtbl_index;
!
! p = &TREE_VALUE (converted_args);
! binfo = get_binfo (DECL_VIRTUAL_CONTEXT (fn),
! TREE_TYPE (TREE_TYPE (*p)), 0);
*p = convert_pointer_to_real (binfo, *p);
if (TREE_SIDE_EFFECTS (*p))
*p = save_expr (*p);
+ ref = build_indirect_ref (*p, 0);
t = build_pointer_type (TREE_TYPE (fn));
!
! vtbl_type = TREE_TYPE (ref);
! if (TREE_CODE (vtbl_type) == REFERENCE_TYPE)
! vtbl_type = TREE_TYPE (vtbl_type);
! vtbl_index = DECL_VINDEX (fn);
!
! fn = build_vfn_ref (p, ref, vtbl_index);
TREE_TYPE (fn) = t;
+
+ /* If doing vtable-gc, record the vtable index from which this
+ call originates. */
+ if (flag_vtable_gc)
+ fn = build (VTABLE_REF, t, fn, vtbl_type, vtbl_index);
}
else if (DECL_INLINE (fn))
fn = inline_conversion (fn);
*************** build_over_call (cand, args, flags)
*** 4286,4291 ****
--- 4301,4307 ----
/* Some built-in function calls will be evaluated at
compile-time in fold (). */
fn = fold (build_call (fn, converted_args));
+
if (VOID_TYPE_P (TREE_TYPE (fn)))
return fn;
fn = require_complete_type (fn);
Index: gcc/cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.358
diff -c -p -d -r1.358 class.c
*** class.c 2001/02/12 09:58:17 1.358
--- class.c 2001/02/13 22:55:21
*************** static tree add_implicitly_declared_memb
*** 134,140 ****
static tree fixed_type_or_null PARAMS ((tree, int *));
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
int, int, tree));
- static void build_vtable_entry_ref PARAMS ((tree, 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));
--- 134,139 ----
*************** build_vbase_path (code, type, expr, path
*** 503,540 ****
/* 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, vtbl, idx)
! tree basetype, vtbl, idx;
{
! static char asm_stmt[] = ".vtable_entry %c0, %c1";
! tree s, i, i2;
! s = build_unary_op (ADDR_EXPR,
! get_vtbl_decl_for_binfo (TYPE_BINFO (basetype)),
! 0);
! s = build_tree_list (build_string (1, "s"), s);
! i = build_array_ref (vtbl, idx);
! if (!flag_vtable_thunks)
! i = build_component_ref (i, pfn_identifier, vtable_entry_type, 0);
! i = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i, 0));
! i2 = build_array_ref (vtbl, build_int_2(0,0));
! i2 = build_c_cast (ptrdiff_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],
! 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
--- 502,569 ----
/* Virtual function things. */
! /* EXP is a VTABLE_REF; TARGET is the result of evaluating the
! interior expression. Build a REG_VTABLE_ENTRY note for the
! reference. If the interior expression is a call, put the
! note on the CALL_INSN, otherwise on the last insn that
! modifies TARGET. */
! rtx
! build_vtable_entry_ref (target, exp)
! rtx target;
! tree exp;
{
! tree type = TREE_OPERAND (exp, 1);
! tree index = TREE_OPERAND (exp, 2);
! tree table;
! HOST_WIDE_INT index_int;
! rtx table_rtx;
! rtx insn;
! table = get_vtbl_decl_for_binfo (TYPE_BINFO (type));
! table_rtx = XEXP (DECL_RTL (table), 0);
! /* ??? This is going away now that the old abi is dead, right? */
! if (! flag_vtable_thunks)
! abort ();
! /* ??? This is supposed to be the offset from the base of the
! symbol. This is almost certainly wrong for the new abi. */
! index_int = tree_low_cst (index, 0);
! index_int *= POINTER_SIZE / BITS_PER_UNIT;
!
! if (GET_CODE (table_rtx) == CONST
! && GET_CODE (XEXP (table_rtx, 0)) == PLUS
! && GET_CODE (XEXP (XEXP (table_rtx, 0), 0)) == SYMBOL_REF
! && GET_CODE (XEXP (XEXP (table_rtx, 0), 1)) == CONST_INT)
! {
! index_int += INTVAL (XEXP (XEXP (table_rtx, 0), 1));
! table_rtx = XEXP (XEXP (table_rtx, 0), 0);
! }
! else if (GET_CODE (table_rtx) != SYMBOL_REF)
! abort ();
!
! table_rtx = plus_constant (table_rtx, index_int);
!
! if (TREE_CODE (TREE_OPERAND (exp, 0)) == CALL_EXPR)
! {
! for (insn = get_last_insn (); ; insn = PREV_INSN (insn))
! if (GET_CODE (insn) == CALL_INSN)
! break;
! }
! else
! {
! target = force_reg (GET_MODE (target), target);
! for (insn = get_last_insn (); ; insn = PREV_INSN (insn))
! if (INSN_P (insn) && reg_set_p (target, insn))
! break;
! }
!
! REG_NOTES (insn)
! = gen_rtx_EXPR_LIST (REG_VTABLE_ENTRY, table_rtx, REG_NOTES (insn));
!
! return target;
}
/* Given an object INSTANCE, return an expression which yields the
*************** tree
*** 546,552 ****
build_vtbl_ref (instance, idx)
tree instance, idx;
{
! tree vtbl, aref;
tree basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
--- 575,581 ----
build_vtbl_ref (instance, idx)
tree instance, idx;
{
! tree vtbl;
tree basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
*************** build_vtbl_ref (instance, idx)
*** 614,625 ****
assemble_external (vtbl);
! if (flag_vtable_gc)
! build_vtable_entry_ref (basetype, vtbl, idx);
!
! aref = build_array_ref (vtbl, idx);
!
! return aref;
}
/* Given an object INSTANCE, return an expression which yields the
--- 643,649 ----
assemble_external (vtbl);
! return build_array_ref (vtbl, idx);
}
/* Given an object INSTANCE, return an expression which yields the
Index: gcc/cp/cp-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.def,v
retrieving revision 1.54
diff -c -p -d -r1.54 cp-tree.def
*** cp-tree.def 2001/01/05 11:41:27 1.54
--- cp-tree.def 2001/02/13 22:55:21
*************** DEFTREECODE (USER_CONV, "user_conv", 'e'
*** 254,259 ****
--- 254,267 ----
DEFTREECODE (AMBIG_CONV, "ambig_conv", 'e', 1)
DEFTREECODE (RVALUE_CONV, "rvalue_conv", 'e', 1)
+ /* Annotate a vtable reference, either through a method call or
+ a member address. Used for -fvtable-gc so that the appropriate
+ information survives until code generation.
+ Operand 0: A call_expr or offset_ref.
+ Operand 1: The vtable tree.
+ Operand 2: The offset into the vtable. */
+ DEFTREECODE (VTABLE_REF, "vtable_ref", 'e', 3)
+
/*
Local variables:
mode:c
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.572
diff -c -p -d -r1.572 cp-tree.h
*** cp-tree.h 2001/02/12 09:58:17 1.572
--- cp-tree.h 2001/02/13 22:55:21
*************** extern tree perform_implicit_conversion
*** 3714,3719 ****
--- 3714,3720 ----
extern tree build_vbase_path PARAMS ((enum tree_code, tree, tree, tree, int));
extern tree build_vtbl_ref PARAMS ((tree, tree));
extern tree build_vfn_ref PARAMS ((tree *, tree, tree));
+ extern struct rtx_def *build_vtable_entry_ref PARAMS ((struct rtx_def *, tree));
extern tree get_vtable_decl PARAMS ((tree, int));
extern void add_method PARAMS ((tree, tree, int));
extern int currently_open_class PARAMS ((tree));
Index: gcc/cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.437
diff -c -p -d -r1.437 decl2.c
*** decl2.c 2001/02/12 09:58:17 1.437
--- decl2.c 2001/02/13 22:55:21
*************** static void
*** 2582,2605 ****
output_vtable_inherit (vars)
tree vars;
{
tree parent;
- rtx op[2];
! op[0] = 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;
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 */
}
else
my_friendly_abort (980826);
! output_asm_insn (".vtable_inherit %c0, %c1", op);
}
static int
--- 2582,2607 ----
output_vtable_inherit (vars)
tree vars;
{
+ rtx table, parent_table;
tree parent;
! /* Strip the MEM to yield the bare address. */
! table = XEXP (DECL_RTL (vars), 0);
parent = binfo_for_vtable (vars);
if (parent == TYPE_BINFO (DECL_CONTEXT (vars)))
! /* No parent vtable. */
! parent_table = const0_rtx;
else if (parent)
{
parent = get_vtbl_decl_for_binfo (TYPE_BINFO (BINFO_TYPE (parent)));
! parent_table = XEXP (DECL_RTL (parent), 0);
}
else
my_friendly_abort (980826);
! asm_emit_vtable_inherit (table, parent_table);
}
static int
Index: gcc/cp/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/expr.c,v
retrieving revision 1.56
diff -c -p -d -r1.56 expr.c
*** expr.c 2001/02/12 09:58:18 1.56
--- expr.c 2001/02/13 22:55:21
*************** cplus_expand_expr (exp, target, tmode, m
*** 103,112 ****
target, tmode, modifier);
case OFFSET_REF:
! {
! return expand_expr (default_conversion (resolve_offset_ref (exp)),
! target, tmode, EXPAND_NORMAL);
! }
case THROW_EXPR:
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
--- 103,110 ----
target, tmode, modifier);
case OFFSET_REF:
! return expand_expr (default_conversion (resolve_offset_ref (exp)),
! target, tmode, EXPAND_NORMAL);
case THROW_EXPR:
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
*************** cplus_expand_expr (exp, target, tmode, m
*** 117,128 ****
/* We don't need to generate any code for an empty class. */
return const0_rtx;
default:
return c_expand_expr (exp, target, tmode, modifier);
}
- my_friendly_abort (40);
- /* NOTREACHED */
- return NULL;
}
void
--- 115,127 ----
/* We don't need to generate any code for an empty class. */
return const0_rtx;
+ case VTABLE_REF:
+ target = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
+ return build_vtable_entry_ref (target, exp);
+
default:
return c_expand_expr (exp, target, tmode, modifier);
}
}
void
Index: gcc/cp/lex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/lex.c,v
retrieving revision 1.237
diff -c -p -d -r1.237 lex.c
*** lex.c 2001/02/12 09:58:18 1.237
--- lex.c 2001/02/13 22:55:22
*************** static void
*** 256,261 ****
--- 256,266 ----
cxx_post_options ()
{
cpp_post_options (parse_in);
+
+ #ifndef HAVE_AS_VTABLE_GC
+ if (flag_vtable_gc)
+ warning ("-fvtable-gc not supported for this target.");
+ #endif
}
static void
More information about the Gcc-patches
mailing list