Thu Nov 20 14:42:15 1997 Jason Merrill <jason@yorick.cygnus.com>
- * Makefile.in (LIB2FUNCS): Remove C++ memory management support.
- * libgcc2.c: Remove __builtin_new, __builtin_vec_new, set_new_handler,
- __builtin_delete, and __builtin_vec_delete.
-
* except.c (output_exception_table): Don't bother with
__EXCEPTION_END__.
_fixunsdfsi _fixunssfsi _fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi \
_fixxfdi _fixunsxfdi _floatdixf _fixunsxfsi \
_fixtfdi _fixunstfdi _floatditf \
- __gcc_bcmp _varargs __dummy _eprintf \
- _bb _shtab _clear_cache _trampoline __main _exit \
+ __gcc_bcmp _varargs __dummy _eprintf _op_new _op_vnew _new_handler \
+ _op_delete _op_vdel _bb _shtab _clear_cache _trampoline __main _exit \
_ctors _eh _pure
# The files that "belong" in CONFIG_H are deliberately omitted
Fri Nov 21 12:22:07 1997 Jason Merrill <jason@yorick.cygnus.com>
- * except.c (expand_start_eh_spec): Use the try/catch code.
- (expand_end_eh_spec): Likewise. Call __check_eh_spec instead of
- doing everything inline.
- (init_exception_processing): throw_type_match now takes
- const void pointers.
- * exception.cc (__check_eh_spec): New fn.
- * inc/exception: Neither terminate nor unexpected return.
- * decl.c: Make const_ptr_type_node public.
- * tinfo2.cc (__throw_type_match_rtti): Take the typeinfos constly.
-
* except.c (expand_start_catch_block): We only need the rethrow
region for non-sjlj exceptions.
(expand_end_catch_block): Likewise. Use outer_context_label_stack.
Thu Nov 20 14:40:17 1997 Jason Merrill <jason@yorick.cygnus.com>
- * Make-lang.in (CXX_LIB2FUNCS): Add new op new and op delete objs.
- (various.o): Likewise.
- * inc/new: Add placement deletes. Add throw specs for default new.
- * new.cc (set_new_handler): Move here from libgcc2.
- * new1.cc (new (nothrow)): Catch a bad_alloc thrown from the handler.
- (new): Move from libgcc2. Throw bad_alloc.
- * new2.cc: Move the rest of the op news and op deletes from libgcc2.
- * decl.c (init_decl_processing): Update exception specs on new and
- delete.
-
* method.c (build_decl_overload_real): Don't mess with global
placement delete.
$(srcdir)/cp/inc/new $(srcdir)/cp/inc/new.h
# Extra code to include in libgcc2.
-CXX_LIB2FUNCS = tinfo.o tinfo2.o new.o opnew.o opnewnt.o opvnew.o opvnewnt.o \
- opdel.o opdelnt.o opvdel.o opvdelnt.o exception.o
+CXX_LIB2FUNCS = tinfo.o tinfo2.o new.o new1.o new2.o exception.o
CXX_LIB2SRCS = $(srcdir)/cp/new.cc $(srcdir)/cp/new1.cc $(srcdir)/cp/new2.cc \
$(srcdir)/cp/exception.cc $(srcdir)/cp/tinfo.cc \
$(srcdir)/cp/tinfo2.cc $(srcdir)/cp/tinfo.h
new.o: cc1plus $(srcdir)/cp/new.cc
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new.cc
-opnew.o: cc1plus $(srcdir)/cp/new1.cc
+new1.o: cc1plus $(srcdir)/cp/new1.cc
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/cp/new1.cc -DL_op_new -o opnew.o
-opnewnt.o: cc1plus $(srcdir)/cp/new1.cc
+ -c $(srcdir)/cp/new1.cc
+new2.o: cc1plus $(srcdir)/cp/new2.cc
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/cp/new1.cc -DL_op_newnt -o opnewnt.o
-opvnew.o: cc1plus $(srcdir)/cp/new2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/cp/new2.cc -DL_op_vnew -o opvnew.o
-opvnewnt.o: cc1plus $(srcdir)/cp/new2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/cp/new2.cc -DL_op_vnewnt -o opvnewnt.o
-opdel.o: cc1plus $(srcdir)/cp/new2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/cp/new2.cc -DL_op_delete -o opdel.o
-opdelnt.o: cc1plus $(srcdir)/cp/new2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/cp/new2.cc -DL_op_delnt -o opdelnt.o
-opvdel.o: cc1plus $(srcdir)/cp/new2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/cp/new2.cc -DL_op_vdel -o opvdel.o
-opvdelnt.o: cc1plus $(srcdir)/cp/new2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/cp/new2.cc -DL_op_vdelnt -o opvdelnt.o
+ -c $(srcdir)/cp/new2.cc
# We want to update cplib2.txt if any of the source files change...
cplib2.txt: $(CXX_LIB2SRCS) $(CXX_EXTRA_HEADERS) cplib2.ready
/* Nodes for types `void *' and `const void *'. */
tree ptr_type_node;
-tree const_ptr_type_node;
+static tree const_ptr_type_node;
/* Nodes for types `char *' and `const char *'. */
/* Now, C++. */
current_lang_name = lang_name_cplusplus;
- {
- tree bad_alloc_type_node = xref_tag
- (class_type_node, get_identifier ("bad_alloc"), NULL_TREE, 1);
- tree newtype = build_exception_variant
- (ptr_ftype_sizetype, build_tree_list (NULL_TREE, bad_alloc_type_node));
- tree deltype = build_exception_variant
- (void_ftype_ptr, build_tree_list (NULL_TREE, NULL_TREE));
- auto_function (ansi_opname[(int) NEW_EXPR], newtype, NOT_BUILT_IN);
- auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype, NOT_BUILT_IN);
- auto_function (ansi_opname[(int) DELETE_EXPR], deltype, NOT_BUILT_IN);
- auto_function (ansi_opname[(int) VEC_DELETE_EXPR], deltype, NOT_BUILT_IN);
- }
+ auto_function (ansi_opname[(int) NEW_EXPR], ptr_ftype_sizetype,
+ NOT_BUILT_IN);
+ auto_function (ansi_opname[(int) VEC_NEW_EXPR], ptr_ftype_sizetype,
+ NOT_BUILT_IN);
+ auto_function (ansi_opname[(int) DELETE_EXPR], void_ftype_ptr,
+ NOT_BUILT_IN);
+ auto_function (ansi_opname[(int) VEC_DELETE_EXPR], void_ftype_ptr,
+ NOT_BUILT_IN);
abort_fndecl
= define_function ("__pure_virtual", void_ftype,
extern int throw_used;
extern rtx catch_clauses;
-extern tree const_ptr_type_node;
/* ========================================================================= */
? "__throw_type_match_rtti"
: "__throw_type_match",
build_function_type (ptr_type_node,
- tree_cons (NULL_TREE, const_ptr_type_node,
- tree_cons (NULL_TREE, const_ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
void_list_node)))),
NOT_BUILT_IN, NULL_PTR);
#endif /* DWARF2_UNWIND_INFO */
}
-/* An exception spec is implemented more or less like:
-
- try {
- function body;
- } catch (...) {
- void *p[] = { typeid(raises) };
- __check_eh_spec (p, count);
- }
-
- __check_eh_spec in exception.cc handles all the details. */
void
expand_start_eh_spec ()
{
- expand_start_try_stmts ();
+ expand_eh_region_start ();
}
static void
expand_end_eh_spec (raises)
tree raises;
{
- tree tmp, fn, decl, types = NULL_TREE;
- int count = 0;
-
- expand_start_all_catch ();
- expand_start_catch_block (NULL_TREE, NULL_TREE);
+ tree expr, second_try;
+ rtx check = gen_label_rtx ();
+ rtx cont;
+ rtx ret = gen_reg_rtx (Pmode);
+ rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node));
+ rtx end = gen_label_rtx ();
+
+ expr = make_node (RTL_EXPR);
+ TREE_TYPE (expr) = void_type_node;
+ RTL_EXPR_RTL (expr) = const0_rtx;
+ TREE_SIDE_EFFECTS (expr) = 1;
+ do_pending_stack_adjust ();
+ start_sequence_for_rtl_expr (expr);
+ cont = gen_label_rtx ();
+ emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
+ emit_jump (check);
+ emit_label (cont);
+ jumpif (make_tree (integer_type_node, flag), end);
+ do_function_call (Terminate, NULL_TREE, NULL_TREE);
+ assemble_external (TREE_OPERAND (Terminate, 0));
+ emit_barrier ();
+ do_pending_stack_adjust ();
+ RTL_EXPR_SEQUENCE (expr) = get_insns ();
+ end_sequence ();
+
+ second_try = expr;
- /* Build up an array of type_infos. */
- for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
- {
- types = expr_tree_cons
- (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
- ++count;
- }
+ expr = make_node (RTL_EXPR);
+ TREE_TYPE (expr) = void_type_node;
+ RTL_EXPR_RTL (expr) = const0_rtx;
+ TREE_SIDE_EFFECTS (expr) = 1;
+ do_pending_stack_adjust ();
+ start_sequence_for_rtl_expr (expr);
- types = build_nt (CONSTRUCTOR, NULL_TREE, types);
- TREE_HAS_CONSTRUCTOR (types) = 1;
+ cont = gen_label_rtx ();
+ emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
+ emit_jump (check);
+ emit_label (cont);
+ jumpif (make_tree (integer_type_node, flag), end);
+ expand_eh_region_start ();
+ do_function_call (Unexpected, NULL_TREE, NULL_TREE);
+ assemble_external (TREE_OPERAND (Unexpected, 0));
+ emit_barrier ();
- /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
- tmp = build_array_type (const_ptr_type_node, NULL_TREE);
- decl = build_decl (VAR_DECL, NULL_TREE, tmp);
- DECL_ARTIFICIAL (decl) = 1;
- DECL_INITIAL (decl) = types;
- cp_finish_decl (decl, types, NULL_TREE, 0, 0);
+ expand_eh_region_end (second_try);
+
+ emit_label (check);
+ emit_move_insn (flag, const1_rtx);
+ cont = gen_label_rtx ();
- decl = decay_conversion (decl);
+ push_eh_info ();
- fn = get_identifier ("__check_eh_spec");
- if (IDENTIFIER_GLOBAL_VALUE (fn))
- fn = IDENTIFIER_GLOBAL_VALUE (fn);
- else
+ while (raises)
{
- push_obstacks_nochange ();
- end_temporary_allocation ();
+ tree exp;
+ tree match_type = TREE_VALUE (raises);
+
+ if (match_type)
+ {
+ /* check TREE_VALUE (raises) here */
+ exp = get_eh_value ();
+ exp = expr_tree_cons (NULL_TREE,
+ build_eh_type_type (match_type),
+ expr_tree_cons (NULL_TREE,
+ get_eh_type (),
+ expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
+ exp = build_function_call (CatchMatch, exp);
+ assemble_external (TREE_OPERAND (CatchMatch, 0));
+
+ jumpif (exp, cont);
+ }
- tmp = tree_cons
- (NULL_TREE, integer_type_node, tree_cons
- (NULL_TREE, TREE_TYPE (decl), void_list_node));
- tmp = build_function_type (void_type_node, tmp);
-
- fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
- DECL_EXTERNAL (fn) = 1;
- TREE_PUBLIC (fn) = 1;
- DECL_ARTIFICIAL (fn) = 1;
- TREE_THIS_VOLATILE (fn) = 1;
- pushdecl_top_level (fn);
- make_function_rtl (fn);
- assemble_external (fn);
- pop_obstacks ();
+ raises = TREE_CHAIN (raises);
}
-
- tmp = expr_tree_cons (NULL_TREE, build_int_2 (count, 0), expr_tree_cons
- (NULL_TREE, decl, NULL_TREE));
- tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp);
- expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
- expand_end_catch_block ();
- expand_end_all_catch ();
+ emit_move_insn (flag, const0_rtx);
+ emit_label (cont);
+ emit_indirect_jump (ret);
+ emit_label (end);
+
+ do_pending_stack_adjust ();
+ RTL_EXPR_SEQUENCE (expr) = get_insns ();
+ end_sequence ();
+
+ expand_eh_region_end (expr);
}
/* This is called to expand all the toplevel exception handling
terminate ();
}
-static unexpected_handler __unexpected_func __attribute__((__noreturn__))
- = __default_unexpected;
+static unexpected_handler __unexpected_func = __default_unexpected;
terminate_handler
set_terminate (terminate_handler func)
/* otherwise __throw will call terminate(); don't crash here. */
}
-/* As per [except.unexpected]:
- If an exception is thrown, we check it against the spec. If it doesn't
- match, we call unexpected (). If unexpected () throws, we check that
- exception against the spec. If it doesn't match, if the spec allows
- bad_exception we throw that; otherwise we call terminate ().
-
- The compiler treats an exception spec as a try block with a generic
- handler that just calls this function with a list of the allowed
- exception types, so we have an active exception that can be rethrown.
-
- This function does not return. */
-
-extern "C" void
-__check_eh_spec (int n, const void **spec)
-{
- cp_eh_info *p = __cp_exception_info ();
-
- for (int i = 0; i < n; ++i)
- {
- if (__throw_type_match_rtti (spec[i], p->type, p->value))
- throw;
- }
-
- try
- {
- unexpected ();
- }
- catch (...)
- {
- // __exception_info is an artificial var pushed into each catch block.
- p = __exception_info;
- for (int i = 0; i < n; ++i)
- {
- if (__throw_type_match_rtti (spec[i], p->type, p->value))
- throw;
- }
-
- const type_info &bad_exc = typeid (bad_exception);
- for (int i = 0; i < n; ++i)
- {
- if (__throw_type_match_rtti (spec[i], &bad_exc, p->value))
- throw bad_exception ();
- }
-
- terminate ();
- }
-}
-
extern "C" void
__throw_bad_cast (void)
{
#include "new"
const nothrow_t nothrow = { };
-
-new_handler __new_handler;
-
-new_handler
-set_new_handler (new_handler handler)
-{
- new_handler prev_handler = __new_handler;
- __new_handler = handler;
- return prev_handler;
-}
-// Support routines for the -*- C++ -*- dynamic memory management.
+// Support routine for the -*- C++ -*- dynamic memory management.
// Copyright (C) 1997 Free Software Foundation
// This file is part of GNU CC.
#include "new"
extern "C" void *malloc (size_t);
-extern new_handler __new_handler;
-#define WEAK(x) \
- x __attribute__ ((weak)); \
- x
+typedef void (*vfp)(void);
+extern vfp __new_handler;
+extern void __default_new_handler (void);
-#ifdef L_op_newnt
-WEAK (void * operator new (size_t sz, const nothrow_t&) throw())
+void *operator new (size_t sz, const nothrow_t&) throw()
{
void *p;
+ vfp handler = __new_handler;
/* malloc (0) is unpredictable; avoid it. */
if (sz == 0)
p = (void *) malloc (sz);
while (p == 0)
{
- new_handler handler = __new_handler;
if (! handler)
return 0;
- try
- {
- handler ();
- }
- catch (bad_alloc &)
- {
- return 0;
- }
-
- p = (void *) malloc (sz);
- }
-
- return p;
-}
-#endif
-
-#ifdef L_op_new
-WEAK (void * operator new (size_t sz) throw (std::bad_alloc))
-{
- void *p;
-
- /* malloc (0) is unpredictable; avoid it. */
- if (sz == 0)
- sz = 1;
- p = (void *) malloc (sz);
- while (p == 0)
- {
- new_handler handler = __new_handler;
- if (! handler)
- throw bad_alloc ();
- handler ();
+ (*handler) ();
p = (void *) malloc (sz);
}
-
+
return p;
}
-#endif
-// Boilerplate support routines for -*- C++ -*- dynamic memory management.
+// Support routine for the -*- C++ -*- dynamic memory management.
// Copyright (C) 1997 Free Software Foundation
// This file is part of GNU CC.
#include "new"
-extern "C" void free (void *);
-
-#define WEAK(x) \
- x __attribute__ ((weak)); \
- x
-
-#ifdef L_op_vnew
-WEAK(void * operator new[] (size_t sz) throw (std::bad_alloc))
-{
- return ::operator new(sz);
-}
-#endif
-
-#ifdef L_op_vnewnt
-WEAK(void *operator new[] (size_t sz, const nothrow_t& nothrow) throw())
+void *operator new[] (size_t sz, const nothrow_t& nothrow) throw()
{
return ::operator new(sz, nothrow);
}
-#endif
-
-#ifdef L_op_delete
-WEAK (void operator delete (void *ptr) throw ())
-{
- if (ptr)
- free (ptr);
-}
-#endif
-
-#ifdef L_op_vdel
-WEAK (void operator delete[] (void *ptr) throw ())
-{
- if (ptr)
- free (ptr);
-}
-#endif
-
-#ifdef L_op_delnt
-WEAK (void operator delete (void *ptr, const std::nothrow_t&) throw ())
-{
- if (ptr)
- free (ptr);
-}
-#endif
-
-#ifdef L_op_vdelnt
-WEAK (void operator delete[] (void *ptr, const std::nothrow_t&) throw ())
-{
- if (ptr)
- free (ptr);
-}
-#endif
variables and thrown objects. */
extern "C" void*
-__throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r,
- void *objptr)
+__throw_type_match_rtti (void *catch_type_r, void *throw_type_r, void *objptr)
{
const type_info &catch_type = *(const type_info *)catch_type_r;
const type_info &throw_type = *(const type_info *)throw_type_r;
#undef abort
#endif
+#if (SUPPORTS_WEAK == 1) && (defined (ASM_OUTPUT_DEF) || defined (ASM_OUTPUT_WEAK_ALIAS))
+#define WEAK_ALIAS
+#endif
+
/* Permit the tm.h file to select the endianness to use just for this
file. This is used when the endianness is determined when the
compiler is run. */
#endif /* not BLOCK_PROFILER_CODE */
#endif /* L_bb */
\f
+/* Default free-store management functions for C++, per sections 12.5 and
+ 17.3.3 of the Working Paper. */
+
+#ifdef L_op_new
+/* operator new (size_t), described in 17.3.3.5. This function is used by
+ C++ programs to allocate a block of memory to hold a single object. */
+
+typedef void (*vfp)(void);
+extern vfp __new_handler;
+extern void __default_new_handler (void);
+
+#ifdef WEAK_ALIAS
+void * __builtin_new (size_t sz)
+ __attribute__ ((weak, alias ("___builtin_new")));
+void *
+___builtin_new (size_t sz)
+#else
+void *
+__builtin_new (size_t sz)
+#endif
+{
+ void *p;
+ vfp handler = (__new_handler) ? __new_handler : __default_new_handler;
+
+ /* malloc (0) is unpredictable; avoid it. */
+ if (sz == 0)
+ sz = 1;
+ p = (void *) malloc (sz);
+ while (p == 0)
+ {
+ (*handler) ();
+ p = (void *) malloc (sz);
+ }
+
+ return p;
+}
+#endif /* L_op_new */
+
+#ifdef L_op_vnew
+/* void * operator new [] (size_t), described in 17.3.3.6. This function
+ is used by C++ programs to allocate a block of memory for an array. */
+
+extern void * __builtin_new (size_t);
+
+#ifdef WEAK_ALIAS
+void * __builtin_vec_new (size_t sz)
+ __attribute__ ((weak, alias ("___builtin_vec_new")));
+void *
+___builtin_vec_new (size_t sz)
+#else
+void *
+__builtin_vec_new (size_t sz)
+#endif
+{
+ return __builtin_new (sz);
+}
+#endif /* L_op_vnew */
+
+#ifdef L_new_handler
+/* set_new_handler (fvoid_t *) and the default new handler, described in
+ 17.3.3.2 and 17.3.3.5. These functions define the result of a failure
+ to allocate the amount of memory requested from operator new or new []. */
+
+#ifndef inhibit_libc
+/* This gets us __GNU_LIBRARY__. */
+#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
+#include <stdio.h>
+
+#ifdef __GNU_LIBRARY__
+ /* Avoid forcing the library's meaning of `write' on the user program
+ by using the "internal" name (for use within the library) */
+#define write(fd, buf, n) __write((fd), (buf), (n))
+#endif
+#endif /* inhibit_libc */
+
+typedef void (*vfp)(void);
+void __default_new_handler (void);
+
+vfp __new_handler = (vfp) 0;
+
+vfp
+set_new_handler (vfp handler)
+{
+ vfp prev_handler;
+
+ prev_handler = __new_handler;
+ if (handler == 0) handler = __default_new_handler;
+ __new_handler = handler;
+ return prev_handler;
+}
+
+#define MESSAGE "Virtual memory exceeded in `new'\n"
+
+void
+__default_new_handler ()
+{
+#ifndef inhibit_libc
+ /* don't use fprintf (stderr, ...) because it may need to call malloc. */
+ /* This should really print the name of the program, but that is hard to
+ do. We need a standard, clean way to get at the name. */
+ write (2, MESSAGE, sizeof (MESSAGE));
+#endif
+ /* don't call exit () because that may call global destructors which
+ may cause a loop. */
+ _exit (-1);
+}
+#endif
+
+#ifdef L_op_delete
+/* operator delete (void *), described in 17.3.3.3. This function is used
+ by C++ programs to return to the free store a block of memory allocated
+ as a single object. */
+
+#ifdef WEAK_ALIAS
+void __builtin_delete (void *ptr)
+ __attribute__ ((weak, alias ("___builtin_delete")));
+void
+___builtin_delete (void *ptr)
+#else
+void
+__builtin_delete (void *ptr)
+#endif
+{
+ if (ptr)
+ free (ptr);
+}
+#endif
+
+#ifdef L_op_vdel
+/* operator delete [] (void *), described in 17.3.3.4. This function is
+ used by C++ programs to return to the free store a block of memory
+ allocated as an array. */
+
+extern void __builtin_delete (void *);
+
+#ifdef WEAK_ALIAS
+void __builtin_vec_delete (void *ptr)
+ __attribute__ ((weak, alias ("___builtin_vec_delete")));
+void
+___builtin_vec_delete (void *ptr)
+#else
+void
+__builtin_vec_delete (void *ptr)
+#endif
+{
+ __builtin_delete (ptr);
+}
+#endif
+
+/* End of C++ free-store management functions */
+\f
#ifdef L_shtab
unsigned int __shtab[] = {
0x00000001, 0x00000002, 0x00000004, 0x00000008,