/* More subroutines needed by GCC output code on some machines. */
/* Compile this one with gcc. */
-/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU CC.
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* As a special exception, if you link this library with files
- compiled with GCC to produce an executable, this does not cause
- the resulting executable to be covered by the GNU General Public License.
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */
do not apply. */
#include "tconfig.h"
+#include "machmode.h"
#ifndef L_trampoline
-#include "gstddef.h"
+#include <stddef.h>
#endif
/* Don't use `fancy_abort' here even if config.h says to use it. */
typedef unsigned int UDItype __attribute__ ((mode (DI)));
typedef float SFtype __attribute__ ((mode (SF)));
typedef float DFtype __attribute__ ((mode (DF)));
-#if 0
+#if LONG_DOUBLE_TYPE_SIZE == 96
typedef float XFtype __attribute__ ((mode (XF)));
#endif
#if LONG_DOUBLE_TYPE_SIZE == 128
typedef float TFtype __attribute__ ((mode (TF)));
#endif
-/* Make sure that we don't accidentaly use any normal C language built-in
+#if BITS_PER_WORD==16
+typedef int word_type __attribute__ ((mode (HI)));
+#endif
+#if BITS_PER_WORD==32
+typedef int word_type __attribute__ ((mode (SI)));
+#endif
+#if BITS_PER_WORD==64
+typedef int word_type __attribute__ ((mode (DI)));
+#endif
+
+/* Make sure that we don't accidentally use any normal C language built-in
type names in the first part of this file. Instead we want to use *only*
the type names defined above. The following macro definitions insure
- that if we *do* accidently use soem normal C language built-in type name,
+ that if we *do* accidentally use some normal C language built-in type name,
we will get a syntax error. */
#define char bogus_type
extern DItype __fixunssfdi (SFtype a);
extern DItype __fixunsdfdi (DFtype a);
+#if LONG_DOUBLE_TYPE_SIZE == 96
+extern DItype __fixunsxfdi (XFtype a);
+#endif
+#if LONG_DOUBLE_TYPE_SIZE == 128
+extern DItype __fixunstfdi (TFtype a);
+#endif
\f
#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
#if defined (L_divdi3) || defined (L_moddi3)
}
#endif
\f
+#ifdef L_ffsdi2
+DItype
+__ffsdi2 (u)
+ DItype u;
+{
+ DIunion uu, w;
+ uu.ll = u;
+ w.s.high = 0;
+ w.s.low = ffs (uu.s.low);
+ if (w.s.low != 0)
+ return w.ll;
+ w.s.low = ffs (uu.s.high);
+ if (w.s.low != 0)
+ {
+ w.s.low += BITS_PER_UNIT * sizeof (SItype);
+ return w.ll;
+ }
+ return w.ll;
+}
+#endif
+\f
#ifdef L_muldi3
DItype
__muldi3 (u, v)
if ((SItype) d >= 0)
{
- if (a1 < d - a1 - (a0 >> 31))
+ if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
{
/* dividend, divisor, and quotient are nonnegative */
sdiv_qrnnd (q, r, a1, a0, d);
else
{
/* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
- sub_ddmmss (c1, c0, a1, a0, d >> 1, d << 31);
+ sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
/* Divide (c1*2^32 + c0) by d */
sdiv_qrnnd (q, r, c1, c0, d);
/* Add 2^31 to quotient */
- q += 1 << 31;
+ q += (USItype) 1 << (SI_TYPE_SIZE - 1);
}
}
else
{
b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
c1 = a1 >> 1; /* A/2 */
- c0 = (a1 << 31) + (a0 >> 1);
+ c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
{
#ifdef L_divdi3
UDItype __udivmoddi4 ();
+
DItype
__divdi3 (u, v)
DItype u, v;
__umoddi3 (u, v)
UDItype u, v;
{
- DItype w;
+ UDItype w;
(void) __udivmoddi4 (u, v, &w);
#endif
\f
#ifdef L_cmpdi2
-SItype
+word_type
__cmpdi2 (a, b)
DItype a, b;
{
#endif
#ifdef L_ucmpdi2
-SItype
+word_type
__ucmpdi2 (a, b)
DItype a, b;
{
}
#endif
+#if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
+#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+
+DItype
+__fixunsxfdi (a)
+ XFtype a;
+{
+ XFtype b;
+ UDItype v;
+
+ if (a < 0)
+ return 0;
+
+ /* Compute high word of result, as a flonum. */
+ b = (a / HIGH_WORD_COEFF);
+ /* Convert that to fixed (but not to DItype!),
+ and shift it into the high word. */
+ v = (USItype) b;
+ v <<= WORD_SIZE;
+ /* Remove high part from the XFtype, leaving the low part as flonum. */
+ a -= (XFtype)v;
+ /* Convert that to fixed (but not to DItype!) and add it in.
+ Sometimes A comes out negative. This is significant, since
+ A has more bits than a long int does. */
+ if (a < 0)
+ v -= (USItype) (- a);
+ else
+ v += (USItype) a;
+ return v;
+}
+#endif
+
+#if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
+DItype
+__fixxfdi (a)
+ XFtype a;
+{
+ if (a < 0)
+ return - __fixunsxfdi (-a);
+ return __fixunsxfdi (a);
+}
+#endif
+
#ifdef L_fixunsdfdi
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
}
#endif
+#if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
+#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
+#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+
+XFtype
+__floatdixf (u)
+ DItype u;
+{
+ XFtype d;
+ SItype negate = 0;
+
+ if (u < 0)
+ u = -u, negate = 1;
+
+ d = (USItype) (u >> WORD_SIZE);
+ d *= HIGH_HALFWORD_COEFF;
+ d *= HIGH_HALFWORD_COEFF;
+ d += (USItype) (u & (HIGH_WORD_COEFF - 1));
+
+ return (negate ? -d : d);
+}
+#endif
+
#if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+#define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
+#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
+#define DF_SIZE 53
+#define SF_SIZE 24
+#else
+#if TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT
+#define DF_SIZE 56
+#define SF_SIZE 24
+#else
+#if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
+#define DF_SIZE 56
+#define SF_SIZE 24
+#else
+#define DF_SIZE 0
+#define SF_SIZE 0
+#endif
+#endif
+#endif
+
SFtype
__floatdisf (u)
DItype u;
{
- SFtype f;
+ /* Do the calculation in DFmode
+ so that we don't lose any of the precision of the high word
+ while multiplying it. */
+ DFtype f;
SItype negate = 0;
if (u < 0)
u = -u, negate = 1;
+ /* Protect against double-rounding error.
+ Represent any low-order bits, that might be truncated in DFmode,
+ by a bit that won't be lost. The bit can go in anywhere below the
+ rounding position of the SFmode. A fixed mask and bit position
+ handles all usual configurations. It doesn't handle the case
+ of 128-bit DImode, however. */
+ if (DF_SIZE < DI_SIZE
+ && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
+ {
+#define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
+ if (u >= ((UDItype) 1 << DF_SIZE))
+ {
+ if ((USItype) u & (REP_BIT - 1))
+ u |= REP_BIT;
+ }
+ }
f = (USItype) (u >> WORD_SIZE);
f *= HIGH_HALFWORD_COEFF;
f *= HIGH_HALFWORD_COEFF;
f += (USItype) (u & (HIGH_WORD_COEFF - 1));
- return (negate ? -f : f);
+ return (SFtype) (negate ? -f : f);
+}
+#endif
+
+#if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
+#include "glimits.h"
+
+USItype
+__fixunsxfsi (a)
+ XFtype a;
+{
+ if (a >= - (DFtype) LONG_MIN)
+ return (SItype) (a + LONG_MIN) - LONG_MIN;
+ return (SItype) a;
}
#endif
#ifdef L_fixunsdfsi
-#include "limits.h"
+#include "glimits.h"
USItype
__fixunsdfsi (a)
#endif
#ifdef L_fixunssfsi
-#include "limits.h"
+#include "glimits.h"
USItype
__fixunssfsi (SFtype a)
#undef unsigned
#undef float
#undef double
+\f
+#ifdef L__gcc_bcmp
+
+/* Like bcmp except the sign is meaningful.
+ Reult is negative if S1 is less than S2,
+ positive if S1 is greater, 0 if S1 and S2 are equal. */
+
+int
+__gcc_bcmp (s1, s2, size)
+ unsigned char *s1, *s2;
+ size_t size;
+{
+ while (size > 0)
+ {
+ unsigned char c1 = *s1++, c2 = *s2++;
+ if (c1 != c2)
+ return c1 - c2;
+ size--;
+ }
+ return 0;
+}
+#endif
+\f\f
#ifdef L_varargs
#ifdef __i860__
#if defined(__svr4__) || defined(__alliant__)
asm (" bri %r1"); /* delayed return */
asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
-#else /* not __SVR4__ */
+#else /* not __svr4__ */
+#if defined(__PARAGON__)
+ /*
+ * we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
+ * and we stand a better chance of hooking into libraries
+ * compiled by PGI. [andyp@ssd.intel.com]
+ */
+ asm (" .text");
+ asm (" .align 4");
+ asm (".globl __builtin_saveregs");
+asm ("__builtin_saveregs:");
+ asm (".globl ___builtin_saveregs");
+asm ("___builtin_saveregs:");
+
+ asm (" andnot 0x0f,sp,sp"); /* round down to 16-byte boundary */
+ asm (" adds -96,sp,sp"); /* allocate stack space for reg save
+ area and also for a new va_list
+ structure */
+ /* Save all argument registers in the arg reg save area. The
+ arg reg save area must have the following layout (according
+ to the svr4 ABI):
+
+ struct {
+ union {
+ float freg[8];
+ double dreg[4];
+ } float_regs;
+ long ireg[12];
+ };
+ */
+
+ asm (" fst.q f8, 0(sp)");
+ asm (" fst.q f12,16(sp)");
+ asm (" st.l r16,32(sp)");
+ asm (" st.l r17,36(sp)");
+ asm (" st.l r18,40(sp)");
+ asm (" st.l r19,44(sp)");
+ asm (" st.l r20,48(sp)");
+ asm (" st.l r21,52(sp)");
+ asm (" st.l r22,56(sp)");
+ asm (" st.l r23,60(sp)");
+ asm (" st.l r24,64(sp)");
+ asm (" st.l r25,68(sp)");
+ asm (" st.l r26,72(sp)");
+ asm (" st.l r27,76(sp)");
+
+ asm (" adds 80,sp,r16"); /* compute the address of the new
+ va_list structure. Put in into
+ r16 so that it will be returned
+ to the caller. */
+
+ /* Initialize all fields of the new va_list structure. This
+ structure looks like:
+
+ typedef struct {
+ unsigned long ireg_used;
+ unsigned long freg_used;
+ long *reg_base;
+ long *mem_ptr;
+ } va_list;
+ */
+
+ asm (" st.l r0, 0(r16)"); /* nfixed */
+ asm (" st.l r0, 4(r16)"); /* nfloating */
+ asm (" st.l sp, 8(r16)"); /* __va_ctl points to __va_struct. */
+ asm (" bri r1"); /* delayed return */
+ asm (" st.l r28,12(r16)"); /* pointer to overflow args */
+#else /* not __PARAGON__ */
asm (" .text");
asm (" .align 4");
asm (" mov r30,sp");
/* recover stack and pass address to start
of data. */
-#endif /* not __SVR4__ */
+#endif /* not __PARAGON__ */
+#endif /* not __svr4__ */
#else /* not __i860__ */
#ifdef __sparc__
asm (".global __builtin_saveregs");
asm (" j $31");
asm (" .end __builtin_saveregs");
#else /* not __mips__, etc. */
+
+void *
__builtin_saveregs ()
{
abort ();
}
+
#endif /* not __mips__ */
#endif /* not __sparc__ */
#endif /* not __i860__ */
#endif
\f
#ifdef L_eprintf
+#ifndef inhibit_libc
+
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
#include <stdio.h>
/* This is used by the `assert' macro. */
fflush (stderr);
abort ();
}
+
+#endif
#endif
#ifdef L_bb
-/* Avoid warning from ranlib about empty object file. */
-void
-__bb_avoid_warning ()
-{}
-#if defined (__sun__) && defined (__mc68000__)
+/* Structure emitted by -a */
struct bb
{
- int initialized;
- char *filename;
- int *counts;
- int ncounts;
- int zero_word;
- int *addresses;
+ long zero_word;
+ const char *filename;
+ long *counts;
+ long ncounts;
+ struct bb *next;
+ const unsigned long *addresses;
+
+ /* Older GCC's did not emit these fields. */
+ long nwords;
+ const char **functions;
+ const long *line_nums;
+ const char **filenames;
};
-extern int ___tcov_init;
+#ifdef BLOCK_PROFILER_CODE
+BLOCK_PROFILER_CODE
+#else
+#ifndef inhibit_libc
+
+/* Simple minded basic block profiling output dumper for
+ systems that don't provde tcov support. At present,
+ it requires atexit and stdio. */
+
+#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
+#include <stdio.h>
+char *ctime ();
+
+#ifdef HAVE_ATEXIT
+extern void atexit (void (*) (void));
+#define ON_EXIT(FUNC,ARG) atexit ((FUNC))
+#else
+#ifdef sun
+extern void on_exit (void*, void*);
+#define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG))
+#endif
+#endif
-__bb_init_func (blocks)
- struct bb *blocks;
+static struct bb *bb_head = (struct bb *)0;
+
+/* Return the number of digits needed to print a value */
+/* __inline__ */ static int num_digits (long value, int base)
{
- if (! ___tcov_init)
- ___tcov_init_func ();
+ int minus = (value < 0 && base != 16);
+ unsigned long v = (minus) ? -value : value;
+ int ret = minus;
- ___bb_link (blocks->filename, blocks->counts, blocks->ncounts);
+ do
+ {
+ v /= base;
+ ret++;
+ }
+ while (v);
+
+ return ret;
}
+void
+__bb_exit_func (void)
+{
+ FILE *file = fopen ("bb.out", "a");
+ long time_value;
+
+ if (!file)
+ perror ("bb.out");
+
+ else
+ {
+ struct bb *ptr;
+
+ /* This is somewhat type incorrect, but it avoids worrying about
+ exactly where time.h is included from. It should be ok unless
+ a void * differs from other pointer formats, or if sizeof(long)
+ is < sizeof (time_t). It would be nice if we could assume the
+ use of rationale standards here. */
+
+ time((void *) &time_value);
+ fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
+
+ /* We check the length field explicitly in order to allow compatibility
+ with older GCC's which did not provide it. */
+
+ for (ptr = bb_head; ptr != (struct bb *)0; ptr = ptr->next)
+ {
+ int i;
+ int func_p = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
+ int line_p = (func_p && ptr->line_nums);
+ int file_p = (func_p && ptr->filenames);
+ long ncounts = ptr->ncounts;
+ long cnt_max = 0;
+ long line_max = 0;
+ long addr_max = 0;
+ int file_len = 0;
+ int func_len = 0;
+ int blk_len = num_digits (ncounts, 10);
+ int cnt_len;
+ int line_len;
+ int addr_len;
+
+ fprintf (file, "File %s, %ld basic blocks \n\n",
+ ptr->filename, ncounts);
+
+ /* Get max values for each field. */
+ for (i = 0; i < ncounts; i++)
+ {
+ const char *p;
+ int len;
+
+ if (cnt_max < ptr->counts[i])
+ cnt_max = ptr->counts[i];
+
+ if (addr_max < ptr->addresses[i])
+ addr_max = ptr->addresses[i];
+
+ if (line_p && line_max < ptr->line_nums[i])
+ line_max = ptr->line_nums[i];
+
+ if (func_p)
+ {
+ p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
+ len = strlen (p);
+ if (func_len < len)
+ func_len = len;
+ }
+
+ if (file_p)
+ {
+ p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
+ len = strlen (p);
+ if (file_len < len)
+ file_len = len;
+ }
+ }
+
+ addr_len = num_digits (addr_max, 16);
+ cnt_len = num_digits (cnt_max, 10);
+ line_len = num_digits (line_max, 10);
+
+ /* Now print out the basic block information. */
+ for (i = 0; i < ncounts; i++)
+ {
+ fprintf (file,
+ " Block #%*d: executed %*ld time(s) address= 0x%.*lx",
+ blk_len, i+1,
+ cnt_len, ptr->counts[i],
+ addr_len, ptr->addresses[i]);
+
+ if (func_p)
+ fprintf (file, " function= %-*s", func_len,
+ (ptr->functions[i]) ? ptr->functions[i] : "<none>");
+
+ if (line_p)
+ fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
+
+ if (file_p)
+ fprintf (file, " file= %s",
+ (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
+
+ fprintf (file, "\n");
+ }
+
+ fprintf (file, "\n");
+ fflush (file);
+ }
+
+ fprintf (file, "\n\n");
+ fclose (file);
+ }
+}
+
+void
+__bb_init_func (struct bb *blocks)
+{
+ /* User is supposed to check whether the first word is non-0,
+ but just in case.... */
+
+ if (blocks->zero_word)
+ return;
+
+#ifdef ON_EXIT
+ /* Initialize destructor. */
+ if (!bb_head)
+ ON_EXIT (__bb_exit_func, 0);
#endif
-#endif
+
+ /* Set up linked list. */
+ blocks->zero_word = 1;
+ blocks->next = bb_head;
+ bb_head = blocks;
+}
+
+#endif /* not inhibit_libc */
+#endif /* not BLOCK_PROFILER_CODE */
+#endif /* L_bb */
\f
-/* frills for C++ */
+/* Default free-store management functions for C++, per sections 12.5 and
+ 17.3.3 of the Working Paper. */
-#ifdef L_builtin_new
-typedef void (*vfp)(void);
+#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 *malloc ();
void *
-__builtin_new (sz)
- size_t sz;
+__builtin_new (size_t sz)
{
void *p;
- p = malloc (sz);
- if (p == 0)
- (*__new_handler) ();
+ /* malloc (0) is unpredictable; avoid it. */
+ if (sz == 0)
+ sz = 1;
+ p = (void *) malloc (sz);
+ while (p == 0)
+ {
+ (*__new_handler) ();
+ p = (void *) malloc (sz);
+ }
+
return p;
}
-#endif
-
-#ifdef L_caps_New
-typedef void (*vfp)(void);
+#endif /* L_op_new */
-extern void *__builtin_new (size_t);
-static void default_new_handler (void);
+#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. */
-vfp __new_handler = default_new_handler;
+extern void * __builtin_new (size_t);
void *
-__builtin_vec_new (p, maxindex, size, ctor)
- void *p;
- size_t maxindex;
- size_t size;
- void (*ctor)(void *);
+__builtin_vec_new (size_t sz)
{
- size_t i;
- size_t nelts = maxindex + 1;
- void *rval;
+ return __builtin_new (sz);
+}
+#endif /* L_op_vnew */
- if (p == 0)
- p = __builtin_new (nelts * size);
+#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 []. */
- rval = p;
+#ifndef inhibit_libc
+/* This gets us __GNU_LIBRARY__. */
+#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
+#include <stdio.h>
- for (i = 0; i < nelts; i++)
- {
- (*ctor) (p);
- p += size;
- }
+#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 */
- return rval;
-}
+typedef void (*vfp)(void);
+void __default_new_handler (void);
+
+vfp __new_handler = __default_new_handler;
vfp
-__set_new_handler (handler)
- vfp handler;
+set_new_handler (vfp handler)
{
vfp prev_handler;
prev_handler = __new_handler;
- if (handler == 0) handler = default_new_handler;
+ if (handler == 0) handler = __default_new_handler;
__new_handler = handler;
return prev_handler;
}
-vfp
-set_new_handler (handler)
- vfp handler;
-{
- return __set_new_handler (handler);
-}
-
#define MESSAGE "Virtual memory exceeded in `new'\n"
-static void
-default_new_handler ()
+void
+__default_new_handler ()
{
/* 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
_exit (-1);
}
#endif
-\f
-#ifdef L_builtin_del
-typedef void (*vfp)(void);
+
+#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. */
void
-__builtin_delete (ptr)
- void *ptr;
+__builtin_delete (void *ptr)
{
if (ptr)
free (ptr);
}
+#endif
-void
-__builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete)
- void *ptr;
- size_t maxindex;
- size_t size;
- void (*dtor)(void *, int);
- int auto_delete;
-{
- size_t i;
- size_t nelts = maxindex + 1;
- void *p = ptr;
-
- ptr += nelts * size;
+#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. */
- for (i = 0; i < nelts; i++)
- {
- ptr -= size;
- (*dtor) (ptr, auto_delete);
- }
+extern void __builtin_delete (void *);
- if (auto_delete_vec)
- __builtin_delete (p);
+void
+__builtin_vec_delete (void *ptr)
+{
+ __builtin_delete (ptr);
}
-
#endif
+/* End of C++ free-store management functions */
+\f
#ifdef L_shtab
unsigned int __shtab[] = {
0x00000001, 0x00000002, 0x00000004, 0x00000008,
__clear_cache (beg, end)
char *beg, *end;
{
+#ifdef CLEAR_INSN_CACHE
+ CLEAR_INSN_CACHE (beg, end);
+#else
#ifdef INSN_CACHE_SIZE
static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
static int initialized = 0;
#endif /* just one plane */
#endif /* Cache is large */
#endif /* Cache exists */
+#endif /* CLEAR_INSN_CACHE */
}
#endif /* L_clear_cache */
TRANSFER_FROM_TRAMPOLINE
#endif
+#if defined (NeXT) && defined (__MACH__)
+
+/* Make stack executable so we can call trampolines on stack.
+ This is called from INITIALIZE_TRAMPOLINE in next.h. */
+#ifdef NeXTStep21
+ #include <mach.h>
+#else
+ #include <mach/mach.h>
+#endif
+
+void
+__enable_execute_stack (addr)
+ char *addr;
+{
+ kern_return_t r;
+ char *eaddr = addr + TRAMPOLINE_SIZE;
+ vm_address_t a = (vm_address_t) addr;
+
+ /* turn on execute access on stack */
+ r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
+ if (r != KERN_SUCCESS)
+ {
+ mach_error("vm_protect VM_PROT_ALL", r);
+ exit(1);
+ }
+
+ /* We inline the i-cache invalidation for speed */
+
+#ifdef CLEAR_INSN_CACHE
+ CLEAR_INSN_CACHE (addr, eaddr);
+#else
+ __clear_cache ((int) addr, (int) eaddr);
+#endif
+}
+
+#endif /* defined (NeXT) && defined (__MACH__) */
+
#ifdef __convex__
/* Make stack executable so we can call trampolines on stack.
}
#endif /* __convex__ */
+#ifdef __DOLPHIN__
+
+/* Modified from the convex -code above. */
+
+#include <sys/param.h>
+#include <errno.h>
+#include <sys/m88kbcs.h>
+
+void
+__enable_execute_stack ()
+{
+ int save_errno;
+ static unsigned long lowest = USRSTACK;
+ unsigned long current = (unsigned long) &save_errno & -NBPC;
+
+ /* Ignore errno being set. memctl sets errno to EINVAL whenever the
+ address is seen as 'negative'. That is the case with the stack. */
+
+ save_errno=errno;
+ if (lowest > current)
+ {
+ unsigned len=lowest-current;
+ memctl(current,len,MCT_TEXT);
+ lowest = current;
+ }
+ else
+ memctl(current,NBPC,MCT_TEXT);
+ errno=save_errno;
+}
+
+#endif /* __DOLPHIN__ */
+
#ifdef __pyr__
+#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#ifdef L__main
#include "gbl-ctors.h"
+/* Some systems use __main in a way incompatible with its use in gcc, in these
+ cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
+ give the same symbol without quotes for an alternative entry point. You
+ must define both, or niether. */
+#ifndef NAME__MAIN
+#define NAME__MAIN "__main"
+#define SYMBOL__MAIN __main
+#endif
/* Run all the global destructors on exit from the program. */
#ifdef DO_GLOBAL_DTORS_BODY
DO_GLOBAL_DTORS_BODY;
#else
- unsigned nptrs = (unsigned HOST_WIDE_INT) __DTOR_LIST__[0];
- unsigned i;
-
- /* Some systems place the number of pointers
- in the first word of the table.
- On other systems, that word is -1.
- In all cases, the table is null-terminated. */
-
- /* If the length is not recorded, count up to the null. */
- if (nptrs == -1)
- for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++);
-
- /* GNU LD format. */
- for (i = nptrs; i >= 1; i--)
- __DTOR_LIST__[i] ();
+ func_ptr *p;
+ for (p = __DTOR_LIST__ + 1; *p; )
+ (*p++) ();
#endif
}
to run __do_global_ctors, so we need not do anything here. */
void
-__main ()
+SYMBOL__MAIN ()
{
/* Support recursive calls to `main': run initializers just once. */
static int initialized = 0;
#endif /* L__main */
\f
-#ifdef L_exit
+#ifdef L_ctors
#include "gbl-ctors.h"
/* We declare the lists here with two elements each,
so that they are valid empty lists if no other definition is loaded. */
#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
+#ifdef __NeXT__
+/* After 2.3, try this definition on all systems. */
+func_ptr __CTOR_LIST__[2] = {0, 0};
+func_ptr __DTOR_LIST__[2] = {0, 0};
+#else
func_ptr __CTOR_LIST__[2];
func_ptr __DTOR_LIST__[2];
+#endif
#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
+#endif /* L_ctors */
+\f
+#ifdef L_exit
+
+#include "gbl-ctors.h"
#ifndef ON_EXIT
extern void __do_global_dtors ();
extern void _cleanup ();
-extern void _exit ();
+extern void _exit () __attribute__ ((noreturn));
void
exit (status)