/* More subroutines needed by GCC output code on some machines. */
/* Compile this one with gcc. */
-/* Copyright (C) 1989, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
#undef abort
#endif
-#if (SUPPORTS_WEAK == 1) && defined (ASM_OUTPUT_DEF)
+#if (SUPPORTS_WEAK == 1) && (defined (ASM_OUTPUT_DEF) || defined (ASM_OUTPUT_WEAK_ALIAS))
#define WEAK_ALIAS
#endif
static inline
#endif
DItype
-__negdi2 (u)
- DItype u;
+__negdi2 (DItype u)
{
DIunion w;
DIunion uu;
}
#endif
\f
+/* Unless shift functions are defined whith full ANSI prototypes,
+ parameter b will be promoted to int if word_type is smaller than an int. */
#ifdef L_lshrdi3
DItype
-__lshrdi3 (u, b)
- DItype u;
- word_type b;
+__lshrdi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
#ifdef L_ashldi3
DItype
-__ashldi3 (u, b)
- DItype u;
- word_type b;
+__ashldi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
#ifdef L_ashrdi3
DItype
-__ashrdi3 (u, b)
- DItype u;
- word_type b;
+__ashrdi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
\f
#ifdef L_ffsdi2
DItype
-__ffsdi2 (u)
- DItype u;
+__ffsdi2 (DItype u)
{
DIunion uu, w;
uu.ll = u;
\f
#ifdef L_muldi3
DItype
-__muldi3 (u, v)
- DItype u, v;
+__muldi3 (DItype u, DItype v)
{
DIunion w;
DIunion uu, vv;
#ifdef L_udiv_w_sdiv
#if defined (sdiv_qrnnd)
USItype
-__udiv_w_sdiv (rp, a1, a0, d)
- USItype *rp, a1, a0, d;
+__udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype d)
{
USItype q, r;
USItype c0, c1, b1;
#else
/* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
USItype
-__udiv_w_sdiv (rp, a1, a0, d)
- USItype *rp, a1, a0, d;
+__udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype d)
{}
#endif
#endif
static inline
#endif
UDItype
-__udivmoddi4 (n, d, rp)
- UDItype n, d;
- UDItype *rp;
+__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
{
DIunion ww;
DIunion nn, dd;
UDItype __udivmoddi4 ();
DItype
-__divdi3 (u, v)
- DItype u, v;
+__divdi3 (DItype u, DItype v)
{
word_type c = 0;
DIunion uu, vv;
#ifdef L_moddi3
UDItype __udivmoddi4 ();
DItype
-__moddi3 (u, v)
- DItype u, v;
+__moddi3 (DItype u, DItype v)
{
word_type c = 0;
DIunion uu, vv;
#ifdef L_umoddi3
UDItype __udivmoddi4 ();
UDItype
-__umoddi3 (u, v)
- UDItype u, v;
+__umoddi3 (UDItype u, UDItype v)
{
UDItype w;
#ifdef L_udivdi3
UDItype __udivmoddi4 ();
UDItype
-__udivdi3 (n, d)
- UDItype n, d;
+__udivdi3 (UDItype n, UDItype d)
{
return __udivmoddi4 (n, d, (UDItype *) 0);
}
\f
#ifdef L_cmpdi2
word_type
-__cmpdi2 (a, b)
- DItype a, b;
+__cmpdi2 (DItype a, DItype b)
{
DIunion au, bu;
#ifdef L_ucmpdi2
word_type
-__ucmpdi2 (a, b)
- DItype a, b;
+__ucmpdi2 (DItype a, DItype b)
{
DIunion au, bu;
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DItype
-__fixunstfdi (a)
- TFtype a;
+__fixunstfdi (TFtype a)
{
TFtype b;
UDItype v;
#if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
DItype
-__fixtfdi (a)
- TFtype a;
+__fixtfdi (TFtype a)
{
if (a < 0)
return - __fixunstfdi (-a);
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DItype
-__fixunsxfdi (a)
- XFtype a;
+__fixunsxfdi (XFtype a)
{
XFtype b;
UDItype v;
#if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
DItype
-__fixxfdi (a)
- XFtype a;
+__fixxfdi (XFtype a)
{
if (a < 0)
return - __fixunsxfdi (-a);
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DItype
-__fixunsdfdi (a)
- DFtype a;
+__fixunsdfdi (DFtype a)
{
DFtype b;
UDItype v;
#ifdef L_fixdfdi
DItype
-__fixdfdi (a)
- DFtype a;
+__fixdfdi (DFtype a)
{
if (a < 0)
return - __fixunsdfdi (-a);
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
XFtype
-__floatdixf (u)
- DItype u;
+__floatdixf (DItype u)
{
XFtype d;
SItype negate = 0;
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
TFtype
-__floatditf (u)
- DItype u;
+__floatditf (DItype u)
{
TFtype d;
SItype negate = 0;
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DFtype
-__floatdidf (u)
- DItype u;
+__floatdidf (DItype u)
{
DFtype d;
SItype negate = 0;
#endif
SFtype
-__floatdisf (u)
- DItype u;
+__floatdisf (DItype u)
{
/* Do the calculation in DFmode
so that we don't lose any of the precision of the high word
#include <limits.h>
USItype
-__fixunsxfsi (a)
- XFtype a;
+__fixunsxfsi (XFtype a)
{
if (a >= - (DFtype) LONG_MIN)
return (SItype) (a + LONG_MIN) - LONG_MIN;
#include <limits.h>
USItype
-__fixunsdfsi (a)
- DFtype a;
+__fixunsdfsi (DFtype a)
{
if (a >= - (DFtype) LONG_MIN)
return (SItype) (a + LONG_MIN) - LONG_MIN;
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;
+__gcc_bcmp (unsigned char *s1, unsigned char *s2, size_t size)
{
while (size > 0)
{
#include <stdio.h>
/* This is used by the `assert' macro. */
void
-__eprintf (string, expression, line, filename)
- const char *string;
- const char *expression;
- int line;
- const char *filename;
+__eprintf (const char *string, const char *expression,
+ int line, const char *filename)
{
fprintf (stderr, string, expression, line, filename);
fflush (stderr);
char *ctime ();
#include "gbl-ctors.h"
+#include "gcov-io.h"
static struct bb *bb_head;
void
__bb_exit_func (void)
{
- FILE *file = fopen ("bb.out", "a");
+ FILE *da_file, *file;
long time_value;
+ int i;
+
+ if (bb_head == 0)
+ return;
+
+ i = strlen (bb_head->filename) - 3;
+
+ if (!strcmp (bb_head->filename+i, ".da"))
+ {
+ /* Must be -fprofile-arcs not -a.
+ Dump data in a form that gcov expects. */
+
+ struct bb *ptr;
+
+ for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
+ {
+ /* If the file exists, and the number of counts in it is the same,
+ then merge them in. */
+
+ if ((da_file = fopen (ptr->filename, "r")) != 0)
+ {
+ long n_counts = 0;
+ unsigned char tmp;
+ int i;
+ int ret = 0;
+
+
+ if (__read_long (&n_counts, da_file, 8) != 0)
+ {
+ fprintf (stderr, "arc profiling: Can't read output file %s.\n",
+ ptr->filename);
+ continue;
+ }
+
+ if (n_counts == ptr->ncounts)
+ {
+ int i;
+
+ for (i = 0; i < n_counts; i++)
+ {
+ long v = 0;
+ unsigned char tmp;
+ int j;
+ int ret = 0;
+
+ if (__read_long (&v, da_file, 8) != 0)
+ {
+ fprintf (stderr, "arc profiling: Can't read output file %s.\n",
+ ptr->filename);
+ break;
+ }
+ ptr->counts[i] += v;
+ }
+ }
+
+ if (fclose (da_file) == EOF)
+ fprintf (stderr, "arc profiling: Error closing output file %s.\n",
+ ptr->filename);
+ }
+ if ((da_file = fopen (ptr->filename, "w")) < 0)
+ {
+ fprintf (stderr, "arc profiling: Can't open output file %s.\n",
+ ptr->filename);
+ continue;
+ }
+
+ /* ??? Should first write a header to the file. Perferably, a 4 byte
+ magic number, 4 bytes containing the time the program was
+ compiled, 4 bytes containing the last modification time of the
+ source file, and 4 bytes indicating the compiler options used.
+
+ That way we can easily verify that the proper source/executable/
+ data file combination is being used from gcov. */
+
+ if (__write_long (ptr->ncounts, da_file, 8) != 0)
+ {
+
+ fprintf (stderr, "arc profiling: Error writing output file %s.\n",
+ ptr->filename);
+ }
+ else
+ {
+ int j;
+ long *count_ptr = ptr->counts;
+ int ret = 0;
+ for (j = ptr->ncounts; j > 0; j--)
+ {
+ if (__write_long (*count_ptr, da_file, 8) != 0)
+ {
+ ret=1;
+ break;
+ }
+ count_ptr++;
+ }
+ if (ret)
+ fprintf (stderr, "arc profiling: Error writing output file %s.\n",
+ ptr->filename);
+ }
+
+ if (fclose (da_file) == EOF)
+ fprintf (stderr, "arc profiling: Error closing output file %s.\n",
+ ptr->filename);
+ }
+
+ return;
+ }
+
+ /* Must be basic block profiling. Emit a human readable output file. */
+
+ file = fopen ("bb.out", "a");
if (!file)
perror ("bb.out");
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 func_p = (ptr->nwords >= sizeof (struct bb)
+ && ptr->nwords <= 1000
+ && ptr->functions);
int line_p = (func_p && ptr->line_nums);
int file_p = (func_p && ptr->filenames);
+ int addr_p = (ptr->addresses != 0);
long ncounts = ptr->ncounts;
long cnt_max = 0;
long line_max = 0;
if (cnt_max < ptr->counts[i])
cnt_max = ptr->counts[i];
- if (addr_max < ptr->addresses[i])
+ if (addr_p && addr_max < ptr->addresses[i])
addr_max = ptr->addresses[i];
if (line_p && line_max < ptr->line_nums[i])
for (i = 0; i < ncounts; i++)
{
fprintf (file,
- " Block #%*d: executed %*ld time(s) address= 0x%.*lx",
+ " Block #%*d: executed %*ld time(s)",
blk_len, i+1,
- cnt_len, ptr->counts[i],
- addr_len, ptr->addresses[i]);
+ cnt_len, ptr->counts[i]);
+
+ if (addr_p)
+ fprintf (file, " address= 0x%.*lx", addr_len,
+ ptr->addresses[i]);
if (func_p)
fprintf (file, " function= %-*s", func_len,
'.gz' from any first parameter to gopen. */
static FILE *
-gopen (fn, mode)
- char *fn;
- char *mode;
+gopen (char *fn, char *mode)
{
int use_gzip;
char *p;
return (FILE *) 0;
p = fn + strlen (fn)-1;
- use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z')) ||
- (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
+ use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
+ || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
if (use_gzip)
{
}
static int
-gclose (f)
- FILE *f;
+gclose (FILE *f)
{
struct stat buf;
- if (f != NULL)
+ if (f != 0)
{
if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
return pclose (f);
{
struct bb_edge **startbucket, **oldnext;
- oldnext = startbucket =
- & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
+ oldnext = startbucket
+ = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
bucket = *startbucket;
for (bucket = *startbucket; bucket;
oldnext = &(bucket->next), bucket = *oldnext)
{
- if ( bucket->src_addr == bb_src &&
- bucket->dst_addr == bb_dst )
+ if (bucket->src_addr == bb_src
+ && bucket->dst_addr == bb_dst)
{
bucket->count++;
*oldnext = bucket->next;
{
struct bb_edge **startbucket, **oldnext;
- oldnext = startbucket =
- & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
+ oldnext = startbucket
+ = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
bucket = *startbucket;
for (bucket = *startbucket; bucket;
oldnext = &(bucket->next), bucket = *oldnext)
{
- if ( bucket->src_addr == bb_dst &&
- bucket->dst_addr == bb_src )
+ if (bucket->src_addr == bb_dst
+ && bucket->dst_addr == bb_src)
{
bucket->count++;
*oldnext = bucket->next;
/* Called upon entering the first function of a file. */
static void
-__bb_init_file (blocks)
- struct bb *blocks;
+__bb_init_file (struct bb *blocks)
{
const struct bb_func *p;
bb_head = blocks;
blocks->flags = 0;
- if (!bb_func_head ||
- !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
+ if (!bb_func_head
+ || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
return;
for (blk = 0; blk < ncounts; blk++)
{
for (p = bb_func_head; p; p = p->next)
{
- if (!strcmp (p->funcname, functions[blk]) &&
- (!p->filename || !strcmp (p->filename, blocks->filename)))
+ if (!strcmp (p->funcname, functions[blk])
+ && (!p->filename || !strcmp (p->filename, blocks->filename)))
{
blocks->flags[blk] |= p->mode;
}
/* Called when entering a function. */
void
-__bb_init_trace_func (blocks, blockno)
- struct bb *blocks;
- unsigned long blockno;
+__bb_init_trace_func (struct bb *blocks, unsigned long blockno)
{
static int trace_init = 0;
#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
void
-__clear_cache (beg, end)
- char *beg, *end;
+__clear_cache (char *beg, char *end)
{
#ifdef CLEAR_INSN_CACHE
CLEAR_INSN_CACHE (beg, end);
#endif
}
-int mprotect(addr, len, prot)
- char *addr;
- int len, prot;
+int mprotect(char *addr, int len, int prot)
{
int np, op;
#endif
void
-__enable_execute_stack (addr)
- char *addr;
+__enable_execute_stack (char *addr)
{
kern_return_t r;
char *eaddr = addr + TRAMPOLINE_SIZE;
}
}
#endif /* __pyr__ */
+
+#if defined (sony_news) && defined (SYSTYPE_BSD)
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <syscall.h>
+#include <machine/sysnews.h>
+
+/* cacheflush function for NEWS-OS 4.2.
+ This function is called from trampoline-initialize code
+ defined in config/mips/mips.h. */
+
+void
+cacheflush (char *beg, int size, int flag)
+{
+ if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
+ {
+ perror ("cache_flush");
+ fflush (stderr);
+ abort ();
+ }
+}
+
+#endif /* sony_news */
#endif /* L_trampoline */
\f
#ifdef L__main
#ifdef DO_GLOBAL_DTORS_BODY
DO_GLOBAL_DTORS_BODY;
#else
- func_ptr *p;
- for (p = __DTOR_LIST__ + 1; *p; )
- (*p++) ();
+ static func_ptr *p = __DTOR_LIST__ + 1;
+ while (*p)
+ {
+ p++;
+ (*(p-1)) ();
+ }
#endif
}
#endif
#ifdef NEED_ATEXIT
# include <errno.h>
-extern void *malloc ();
-extern void *realloc ();
-
-static func_ptr *atexit_chain = NULL;
+static func_ptr *atexit_chain = 0;
static long atexit_chain_length = 0;
static volatile long last_atexit_chain_slot = -1;
{
atexit_chain_length += 32;
if (atexit_chain)
- atexit_chain = realloc (atexit_chain,
- atexit_chain_length * sizeof (func_ptr));
+ atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
+ * sizeof (func_ptr));
else
- atexit_chain = malloc (atexit_chain_length * sizeof (func_ptr));
+ atexit_chain = (func_ptr *) malloc (atexit_chain_length
+ * sizeof (func_ptr));
if (! atexit_chain)
{
atexit_chain_length = 0;
have to define our own exit routine which will get this to happen. */
extern void __do_global_dtors ();
+extern void __bb_exit_func ();
extern void _cleanup ();
extern void _exit () __attribute__ ((noreturn));
void
-exit (status)
- int status;
+exit (int status)
{
#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
#ifdef NEED_ATEXIT
for ( ; last_atexit_chain_slot-- >= 0; )
{
(*atexit_chain[last_atexit_chain_slot + 1]) ();
- atexit_chain[last_atexit_chain_slot + 1] = NULL;
+ atexit_chain[last_atexit_chain_slot + 1] = 0;
}
free (atexit_chain);
- atexit_chain = NULL;
+ atexit_chain = 0;
}
#else /* No NEED_ATEXIT */
__do_global_dtors ();
#endif /* No NEED_ATEXIT */
#endif
+#ifndef inhibit_libc
+ __bb_exit_func ();
+#endif
#ifdef EXIT_BODY
EXIT_BODY;
#else
#else
+void
+__default_terminate ()
+{
+ abort ();
+}
+
+void (*__terminate_func)() = __default_terminate;
+
+void
+__terminate ()
+{
+ (*__terminate_func)();
+}
+
+/* Calls to __sjthrow are generated by the compiler when an exception
+ is raised when using the setjmp/longjmp exception handling codegen
+ method. */
+
+extern void longjmp (void *, int);
+
+extern void *__eh_type;
+
+static void *top_elt[2];
+void **__dynamic_handler_chain = top_elt;
+
+/* Routine to get the head of the current thread's dynamic handler chain
+ use for exception handling.
+
+ TODO: make thread safe. */
+
+void ***
+__get_dynamic_handler_chain ()
+{
+ return &__dynamic_handler_chain;
+}
+
+/* This is used to throw an exception when the setjmp/longjmp codegen
+ method is used for exception handling.
+
+ We call __terminate if there are no handlers left (we know this
+ when the dynamic handler chain is top_elt). Otherwise we run the
+ cleanup actions off the dynamic cleanup stack, and pop the top of
+ the dynamic handler chain, and use longjmp to transfer back to the
+ associated handler. */
+
+void
+__sjthrow ()
+{
+ void ***dhc = __get_dynamic_handler_chain ();
+ void *jmpbuf;
+ void (*func)(void *, int);
+ void *arg;
+ void ***cleanup;
+
+ /* The cleanup chain is one word into the buffer. Get the cleanup
+ chain. */
+ cleanup = (void***)&(*dhc)[1];
+
+ /* If there are any cleanups in the chain, run them now. */
+ if (cleanup[0])
+ {
+ double store[200];
+ void **buf = (void**)store;
+ buf[1] = 0;
+ buf[0] = (*dhc);
+
+ /* try { */
+#ifdef DONT_USE_BUILTIN_SETJMP
+ if (! setjmp (&buf[2]))
+#else
+ if (! __builtin_setjmp (&buf[2]))
+#endif
+ {
+ *dhc = buf;
+ while (cleanup[0])
+ {
+ func = (void(*)(void*, int))cleanup[0][1];
+ arg = (void*)cleanup[0][2];
+
+ /* Update this before running the cleanup. */
+ cleanup[0] = (void **)cleanup[0][0];
+
+ (*func)(arg, 2);
+ }
+ *dhc = buf[0];
+ }
+ /* catch (...) */
+ else
+ {
+ __terminate ();
+ }
+ }
+
+ /* We must call terminate if we try and rethrow an exception, when
+ there is no exception currently active and when there are no
+ handlers left. */
+ if (! __eh_type || (*dhc) == top_elt)
+ __terminate ();
+
+ /* Find the jmpbuf associated with the top element of the dynamic
+ handler chain. The jumpbuf starts two words into the buffer. */
+ jmpbuf = &(*dhc)[2];
+
+ /* Then we pop the top element off the dynamic handler chain. */
+ *dhc = (void**)(*dhc)[0];
+
+ /* And then we jump to the handler. */
+
+#ifdef DONT_USE_BUILTIN_SETJMP
+ longjmp (jmpbuf, 1);
+#else
+ __builtin_longjmp (jmpbuf, 1);
+#endif
+}
+
+/* Run cleanups on the dynamic cleanup stack for the current dynamic
+ handler, then pop the handler off the dynamic handler stack, and
+ then throw. This is used to skip the first handler, and transfer
+ control to the next handler in the dynamic handler stack. */
+
+void
+__sjpopnthrow ()
+{
+ void ***dhc = __get_dynamic_handler_chain ();
+ void *jmpbuf;
+ void (*func)(void *, int);
+ void *arg;
+ void ***cleanup;
+
+ /* The cleanup chain is one word into the buffer. Get the cleanup
+ chain. */
+ cleanup = (void***)&(*dhc)[1];
+
+ /* If there are any cleanups in the chain, run them now. */
+ if (cleanup[0])
+ {
+ double store[200];
+ void **buf = (void**)store;
+ buf[1] = 0;
+ buf[0] = (*dhc);
+
+ /* try { */
+#ifdef DONT_USE_BUILTIN_SETJMP
+ if (! setjmp (&buf[2]))
+#else
+ if (! __builtin_setjmp (&buf[2]))
+#endif
+ {
+ *dhc = buf;
+ while (cleanup[0])
+ {
+ func = (void(*)(void*, int))cleanup[0][1];
+ arg = (void*)cleanup[0][2];
+
+ /* Update this before running the cleanup. */
+ cleanup[0] = (void **)cleanup[0][0];
+
+ (*func)(arg, 2);
+ }
+ *dhc = buf[0];
+ }
+ /* catch (...) */
+ else
+ {
+ __terminate ();
+ }
+ }
+
+ /* Then we pop the top element off the dynamic handler chain. */
+ *dhc = (void**)(*dhc)[0];
+
+ __sjthrow ();
+}
+
typedef struct {
void *start;
void *end;
struct exception_table_node *next;
};
-static int except_table_pos;
-static void *except_pc;
static struct exception_table_node *exception_table_list;
-static exception_table *
-find_exception_table (pc)
- void *pc;
-{
- register struct exception_table_node *table = exception_table_list;
- for ( ; table != 0; table = table->next)
- {
- if (table->start <= pc && table->end > pc)
- return table->table;
- }
- return 0;
-}
-
/* this routine takes a pc, and the address of the exception handler associated
with the closest exception table handler entry associated with that PC,
or 0 if there are no table entries the PC fits in. The algorithm works
an inner block. */
void *
-__find_first_exception_table_match(pc)
-void *pc;
-{
- exception_table *table = find_exception_table (pc);
- int pos = 0;
- int best = 0;
- if (table == 0)
- return (void *) 0;
+__find_first_exception_table_match (void *pc)
+{
+ register struct exception_table_node *tnp;
+ register exception_table *table;
+ int pos;
+ int best;
+
#if 0
- printf ("find_first_exception_table_match(): pc = %x!\n", pc);
+ printf ("find_first_exception_table_match (): pc = %x!\n", pc);
#endif
- except_pc = pc;
+ for (tnp = exception_table_list; tnp != 0; tnp = tnp->next)
+ {
+ if (tnp->start > pc || tnp->end <= pc)
+ continue;
+
+ table = tnp->table;
+ pos = 0;
+ best = 0;
#if 0
- /* We can't do this yet, as we don't know that the table is sorted. */
- do {
- ++pos;
- if (table[pos].start > except_pc)
- /* found the first table[pos].start > except_pc, so the previous
- entry better be the one we want! */
- break;
- } while (table[pos].exception_handler != (void *) -1);
-
- --pos;
- if (table[pos].start <= except_pc && table[pos].end > except_pc)
- {
- except_table_pos = pos;
+ /* We can't do this yet, as we don't know that the table is sorted. */
+ do {
+ ++pos;
+ if (table[pos].start > pc)
+ /* found the first table[pos].start > pc, so the previous
+ entry better be the one we want! */
+ break;
+ } while (table[pos].exception_handler != (void *) -1);
+
+ --pos;
+ if (table[pos].start <= pc && table[pos].end > pc)
+ {
#if 0
- printf ("find_first_eh_table_match(): found match: %x\n", table[pos].exception_handler);
+ printf ("find_first_eh_table_match (): found match: %x\n", table[pos].exception_handler);
#endif
- return table[pos].exception_handler;
- }
+ return table[pos].exception_handler;
+ }
#else
- while (table[++pos].exception_handler != (void *) -1) {
- if (table[pos].start <= except_pc && table[pos].end > except_pc)
- {
- /* This can apply. Make sure it is better or as good as the previous
- best. */
- /* The best one ends first. */
- if (best == 0 || (table[pos].end <= table[best].end
- /* The best one starts last. */
- && table[pos].start >= table[best].start))
- best = pos;
+ while (table[++pos].exception_handler != (void *) -1) {
+ if (table[pos].start <= pc && table[pos].end > pc)
+ {
+ /* This can apply. Make sure it is better or as good as
+ the previous best. */
+ /* The best one ends first. */
+ if (best == 0 || (table[pos].end <= table[best].end
+ /* The best one starts last. */
+ && table[pos].start >= table[best].start))
+ best = pos;
+ }
}
- }
- if (best != 0)
- return table[best].exception_handler;
+ if (best != 0)
+ return table[best].exception_handler;
#endif
+ }
#if 0
- printf ("find_first_eh_table_match(): else: returning NULL!\n");
+ printf ("find_first_eh_table_match (): else: returning NULL!\n");
#endif
return (void *) 0;
}
void *__eh_pc;
+/* See expand_builtin_throw for details. */
+
+void **__eh_ffetmnpc () {
+ static void *buf[2] = {
+ &__find_first_exception_table_match,
+ &__eh_pc
+ };
+ return buf;
+}
+
void
__empty ()
{