- if (bb_tracefile)
- {
- fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
- }
-
- if (bb_hashbuckets)
- {
- struct bb_edge **startbucket, **oldnext;
-
- 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)
- {
- bucket->count++;
- *oldnext = bucket->next;
- bucket->next = *startbucket;
- *startbucket = bucket;
- goto ret;
- }
- }
-
- bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
-
- if (!bucket)
- {
- if (!reported)
- {
- fprintf (stderr, "Profiler: out of memory\n");
- reported = 1;
- }
- }
-
- else
- {
- bucket->src_addr = bb_src;
- bucket->dst_addr = bb_dst;
- bucket->next = *startbucket;
- *startbucket = bucket;
- bucket->count = 1;
- }
- }
-
-ret:
- bb_src = bb_dst;
-
-skip:
- ;
-
- MACHINE_STATE_RESTORE("1")
-
-}
-
-/* Called when returning from a function and `__bb_showret__' is set. */
-
-static void
-__bb_trace_func_ret ()
-{
- struct bb_edge *bucket;
-
- if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
- goto skip;
-
- if (bb_hashbuckets)
- {
- struct bb_edge **startbucket, **oldnext;
-
- 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)
- {
- bucket->count++;
- *oldnext = bucket->next;
- bucket->next = *startbucket;
- *startbucket = bucket;
- goto ret;
- }
- }
-
- bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
-
- if (!bucket)
- {
- if (!reported)
- {
- fprintf (stderr, "Profiler: out of memory\n");
- reported = 1;
- }
- }
-
- else
- {
- bucket->src_addr = bb_dst;
- bucket->dst_addr = bb_src;
- bucket->next = *startbucket;
- *startbucket = bucket;
- bucket->count = 1;
- }
- }
-
-ret:
- bb_dst = bb_src;
-
-skip:
- ;
-
-}
-
-/* Called upon entering the first function of a file. */
-
-static void
-__bb_init_file (struct bb *blocks)
-{
-
- const struct bb_func *p;
- long blk, ncounts = blocks->ncounts;
- const char **functions = blocks->functions;
-
- /* Set up linked list. */
- blocks->zero_word = 1;
- blocks->next = bb_head;
- bb_head = blocks;
-
- blocks->flags = 0;
- if (!bb_func_head
- || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
- return;
-
- for (blk = 0; blk < ncounts; blk++)
- blocks->flags[blk] = 0;
-
- 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)))
- {
- blocks->flags[blk] |= p->mode;
- }
- }
- }
-
-}
-
-/* Called when exiting from a function. */
-
-void
-__bb_trace_ret ()
-{
-
- MACHINE_STATE_SAVE("2")
-
- if (bb_callcount)
- {
- if ((bb_mode & 12) && bb_stacksize > bb_callcount)
- {
- bb_src = bb_stack[bb_callcount];
- if (bb_mode & 8)
- __bb_trace_func_ret ();
- }
-
- bb_callcount -= 1;
- }
-
- MACHINE_STATE_RESTORE("2")
-
-}
-
-/* Called when entering a function. */
-
-void
-__bb_init_trace_func (struct bb *blocks, unsigned long blockno)
-{
- static int trace_init = 0;
-
- MACHINE_STATE_SAVE("3")
-
- if (!blocks->zero_word)
- {
- if (!trace_init)
- {
- trace_init = 1;
- __bb_init_prg ();
- }
- __bb_init_file (blocks);
- }
-
- if (bb_callcount)
- {
-
- bb_callcount += 1;
-
- if (bb_mode & 12)
- {
- if (bb_callcount >= bb_stacksize)
- {
- size_t newsize = bb_callcount + 100;
-
- bb_stack = (unsigned long *) realloc (bb_stack, newsize);
- if (! bb_stack)
- {
- if (!reported)
- {
- fprintf (stderr, "Profiler: out of memory\n");
- reported = 1;
- }
- bb_stacksize = 0;
- goto stack_overflow;
- }
- bb_stacksize = newsize;
- }
- bb_stack[bb_callcount] = bb_src;
-
- if (bb_mode & 4)
- bb_src = 0;
-
- }
-
-stack_overflow:;
-
- }
-
- else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
- {
- bb_callcount = 1;
- bb_src = 0;
-
- if (bb_stack)
- bb_stack[bb_callcount] = bb_src;
- }
-
- MACHINE_STATE_RESTORE("3")
-}
-
-#endif /* not inhibit_libc */
-#endif /* not BLOCK_PROFILER_CODE */
-#endif /* L_bb */
-\f
-#ifdef L_shtab
-unsigned int __shtab[] = {
- 0x00000001, 0x00000002, 0x00000004, 0x00000008,
- 0x00000010, 0x00000020, 0x00000040, 0x00000080,
- 0x00000100, 0x00000200, 0x00000400, 0x00000800,
- 0x00001000, 0x00002000, 0x00004000, 0x00008000,
- 0x00010000, 0x00020000, 0x00040000, 0x00080000,
- 0x00100000, 0x00200000, 0x00400000, 0x00800000,
- 0x01000000, 0x02000000, 0x04000000, 0x08000000,
- 0x10000000, 0x20000000, 0x40000000, 0x80000000
- };
-#endif
-\f
-#ifdef L_clear_cache
-/* Clear part of an instruction cache. */
-
-#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
-
-void
-__clear_cache (char *beg __attribute__((__unused__)),
- char *end __attribute__((__unused__)))
-{
-#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;
- int offset;
- void *start_addr
- void *end_addr;
- typedef (*function_ptr) ();
-
-#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
- /* It's cheaper to clear the whole cache.
- Put in a series of jump instructions so that calling the beginning
- of the cache will clear the whole thing. */
-
- if (! initialized)
- {
- int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH);
- int end_ptr = ptr + INSN_CACHE_SIZE;
-
- while (ptr < end_ptr)
- {
- *(INSTRUCTION_TYPE *)ptr
- = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
- ptr += INSN_CACHE_LINE_WIDTH;
- }
- *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
-
- initialized = 1;
- }
-
- /* Call the beginning of the sequence. */
- (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH))
- ());
-
-#else /* Cache is large. */
-
- if (! initialized)
- {
- int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH);
-
- while (ptr < (int) array + sizeof array)
- {
- *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
- ptr += INSN_CACHE_LINE_WIDTH;
- }
-
- initialized = 1;
- }
-
- /* Find the location in array that occupies the same cache line as BEG. */
-
- offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
- start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
- & -INSN_CACHE_PLANE_SIZE)
- + offset);
-
- /* Compute the cache alignment of the place to stop clearing. */
-#if 0 /* This is not needed for gcc's purposes. */
- /* If the block to clear is bigger than a cache plane,
- we clear the entire cache, and OFFSET is already correct. */
- if (end < beg + INSN_CACHE_PLANE_SIZE)
-#endif
- offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH)
- & (INSN_CACHE_PLANE_SIZE - 1));
-
-#if INSN_CACHE_DEPTH > 1
- end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
- if (end_addr <= start_addr)
- end_addr += INSN_CACHE_PLANE_SIZE;
-
- for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
- {
- int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
- int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
-
- while (addr != stop)
- {
- /* Call the return instruction at ADDR. */
- ((function_ptr) addr) ();
-
- addr += INSN_CACHE_LINE_WIDTH;
- }
- }
-#else /* just one plane */
- do
- {
- /* Call the return instruction at START_ADDR. */
- ((function_ptr) start_addr) ();
-
- start_addr += INSN_CACHE_LINE_WIDTH;
- }
- while ((start_addr % INSN_CACHE_SIZE) != offset);
-#endif /* just one plane */
-#endif /* Cache is large */
-#endif /* Cache exists */
-#endif /* CLEAR_INSN_CACHE */
-}
-
-#endif /* L_clear_cache */
-\f
-#ifdef L_trampoline
-
-/* Jump to a trampoline, loading the static chain address. */
-
-#if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
-
-long getpagesize()
-{
-#ifdef _ALPHA_
- return 8192;
-#else
- return 4096;
-#endif
-}
-
-#ifdef i386
-extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
-#endif
-
-int
-mprotect (char *addr, int len, int prot)
-{
- int np, op;
-
- if (prot == 7)
- np = 0x40;
- else if (prot == 5)
- np = 0x20;
- else if (prot == 4)
- np = 0x10;
- else if (prot == 3)
- np = 0x04;
- else if (prot == 1)
- np = 0x02;
- else if (prot == 0)
- np = 0x01;
-
- if (VirtualProtect (addr, len, np, &op))
- return 0;
- else
- return -1;
-}
-
-#endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
-
-#ifdef TRANSFER_FROM_TRAMPOLINE
-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 (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.
- This is called from INITIALIZE_TRAMPOLINE in convex.h. */
-
-#include <sys/mman.h>
-#include <sys/vmparam.h>
-#include <machine/machparam.h>
-
-void
-__enable_execute_stack ()
-{
- int fp;
- static unsigned lowest = USRSTACK;
- unsigned current = (unsigned) &fp & -NBPG;
-
- if (lowest > current)
- {
- unsigned len = lowest - current;
- mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
- lowest = current;
- }
-
- /* Clear instruction cache in case an old trampoline is in it. */
- asm ("pich");
-}
-#endif /* __convex__ */
-
-#ifdef __sysV88__
-
-/* 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 /* __sysV88__ */
-
-#ifdef __sysV68__
-
-#include <sys/signal.h>
-#include <errno.h>
-
-/* Motorola forgot to put memctl.o in the libp version of libc881.a,
- so define it here, because we need it in __clear_insn_cache below */
-/* On older versions of this OS, no memctl or MCT_TEXT are defined;
- hence we enable this stuff only if MCT_TEXT is #define'd. */
-
-#ifdef MCT_TEXT
-asm("\n\
- global memctl\n\
-memctl:\n\
- movq &75,%d0\n\
- trap &0\n\
- bcc.b noerror\n\
- jmp cerror%\n\
-noerror:\n\
- movq &0,%d0\n\
- rts");
-#endif
-
-/* Clear instruction cache so we can call trampolines on stack.
- This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
-
-void
-__clear_insn_cache ()
-{
-#ifdef MCT_TEXT
- int save_errno;
-
- /* Preserve errno, because users would be surprised to have
- errno changing without explicitly calling any system-call. */
- save_errno = errno;
-
- /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
- No need to use an address derived from _start or %sp, as 0 works also. */
- memctl(0, 4096, MCT_TEXT);
- errno = save_errno;
-#endif
-}
-
-#endif /* __sysV68__ */
-
-#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>
-#include <sys/param.h>
-#include <sys/vmmac.h>
-
-/* Modified from the convex -code above.
- mremap promises to clear the i-cache. */
-
-void
-__enable_execute_stack ()
-{
- int fp;
- if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
- PROT_READ|PROT_WRITE|PROT_EXEC))
- {
- perror ("mprotect in __enable_execute_stack");
- fflush (stderr);
- abort ();
- }
-}
-#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
-#ifndef __CYGWIN__
-#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 neither. */
-#ifndef NAME__MAIN
-#define NAME__MAIN "__main"
-#define SYMBOL__MAIN __main
-#endif
-
-#ifdef INIT_SECTION_ASM_OP
-#undef HAS_INIT_SECTION
-#define HAS_INIT_SECTION
-#endif
-
-#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
-
-/* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
- code to run constructors. In that case, we need to handle EH here, too. */
-
-#ifdef EH_FRAME_SECTION
-#include "frame.h"
-extern unsigned char __EH_FRAME_BEGIN__[];
-#endif
-
-/* Run all the global destructors on exit from the program. */
-
-void
-__do_global_dtors ()
-{
-#ifdef DO_GLOBAL_DTORS_BODY
- DO_GLOBAL_DTORS_BODY;
-#else
- static func_ptr *p = __DTOR_LIST__ + 1;
- while (*p)
- {
- p++;
- (*(p-1)) ();
- }
-#endif
-#ifdef EH_FRAME_SECTION
- __deregister_frame_info (__EH_FRAME_BEGIN__);
-#endif
-}
-#endif
-
-#ifndef HAS_INIT_SECTION
-/* Run all the global constructors on entry to the program. */
-
-void
-__do_global_ctors ()
-{
-#ifdef EH_FRAME_SECTION
- {
- static struct object object;
- __register_frame_info (__EH_FRAME_BEGIN__, &object);
- }
-#endif
- DO_GLOBAL_CTORS_BODY;
- atexit (__do_global_dtors);
-}
-#endif /* no HAS_INIT_SECTION */
-
-#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
-/* Subroutine called automatically by `main'.
- Compiling a global function named `main'
- produces an automatic call to this function at the beginning.
-
- For many systems, this routine calls __do_global_ctors.
- For systems which support a .init section we use the .init section
- to run __do_global_ctors, so we need not do anything here. */
-
-void
-SYMBOL__MAIN ()
-{
- /* Support recursive calls to `main': run initializers just once. */
- static int initialized;
- if (! initialized)
- {
- initialized = 1;
- __do_global_ctors ();
- }
-}
-#endif /* no HAS_INIT_SECTION or INVOKE__main */
-
-#endif /* L__main */
-#endif /* __CYGWIN__ */
-\f
-#ifdef L_ctors
-
-#include "gbl-ctors.h"
-
-/* Provide default definitions for the lists of constructors and
- destructors, so that we don't get linker errors. These symbols are
- intentionally bss symbols, so that gld and/or collect will provide
- the right values. */
-
-/* We declare the lists here with two elements each,
- so that they are valid empty lists if no other definition is loaded.
-
- If we are using the old "set" extensions to have the gnu linker
- collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
- must be in the bss/common section.
-
- Long term no port should use those extensions. But many still do. */
-#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
-#if defined (ASM_OUTPUT_CONSTRUCTOR) || defined (USE_COLLECT2)
-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"
-
-#ifdef NEED_ATEXIT
-
-#ifndef ON_EXIT
-
-# include <errno.h>
-
-static func_ptr *atexit_chain = 0;
-static long atexit_chain_length = 0;
-static volatile long last_atexit_chain_slot = -1;
-
-int
-atexit (func_ptr func)
-{
- if (++last_atexit_chain_slot == atexit_chain_length)
- {
- atexit_chain_length += 32;
- if (atexit_chain)
- atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
- * sizeof (func_ptr));
- else
- atexit_chain = (func_ptr *) malloc (atexit_chain_length
- * sizeof (func_ptr));
- if (! atexit_chain)
- {
- atexit_chain_length = 0;
- last_atexit_chain_slot = -1;
- errno = ENOMEM;
- return (-1);
- }
- }
- atexit_chain[last_atexit_chain_slot] = func;
- return (0);
-}
-
-extern void _cleanup ();
-extern void _exit () __attribute__ ((noreturn));
-
-void
-exit (int status)
-{
- if (atexit_chain)
- {
- for ( ; last_atexit_chain_slot-- >= 0; )
- {
- (*atexit_chain[last_atexit_chain_slot + 1]) ();
- atexit_chain[last_atexit_chain_slot + 1] = 0;
- }
- free (atexit_chain);
- atexit_chain = 0;
- }
-#ifdef EXIT_BODY
- EXIT_BODY;
-#else
- _cleanup ();
-#endif
- _exit (status);
-}
-
-#else /* ON_EXIT */
-
-/* Simple; we just need a wrapper for ON_EXIT. */
-int
-atexit (func_ptr func)
-{
- return ON_EXIT (func);
-}
-
-#endif /* ON_EXIT */
-#endif /* NEED_ATEXIT */
-
-#endif /* L_exit */
-\f
-#ifdef L_eh
-
-#include "gthr.h"
-
-/* Shared exception handling support routines. */
-
-extern void __default_terminate (void) __attribute__ ((__noreturn__));
-
-void
-__default_terminate ()
-{
- abort ();
-}
-
-void (*__terminate_func)() = __default_terminate;
-
-void
-__terminate ()
-{
- (*__terminate_func)();
-}
-
-void *
-__throw_type_match (void *catch_type, void *throw_type, void *obj)
-{
-#if 0
- printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
- catch_type, throw_type);
-#endif
- if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
- return obj;
- return 0;
-}
-
-void
-__empty ()
-{
-}
-\f
-
-/* Include definitions of EH context and table layout */
-
-#include "eh-common.h"
-#ifndef inhibit_libc
-#include <stdio.h>
-#endif
-
-/* Allocate and return a new EH context structure. */
-
-extern void __throw ();
-
-static void *
-new_eh_context ()
-{
- struct eh_full_context {
- struct eh_context c;
- void *top_elt[2];
- } *ehfc = (struct eh_full_context *) malloc (sizeof *ehfc);
-
- if (! ehfc)
- __terminate ();
-
- memset (ehfc, 0, sizeof *ehfc);
-
- ehfc->c.dynamic_handler_chain = (void **) ehfc->top_elt;
-
- /* This should optimize out entirely. This should always be true,
- but just in case it ever isn't, don't allow bogus code to be
- generated. */
-
- if ((void*)(&ehfc->c) != (void*)ehfc)
- __terminate ();
-
- return &ehfc->c;
-}
-
-#if __GTHREADS
-static __gthread_key_t eh_context_key;
-
-/* Destructor for struct eh_context. */
-static void
-eh_context_free (void *ptr)
-{
- __gthread_key_dtor (eh_context_key, ptr);
- if (ptr)
- free (ptr);
-}
-#endif
-
-/* Pointer to function to return EH context. */
-
-static struct eh_context *eh_context_initialize ();
-static struct eh_context *eh_context_static ();
-#if __GTHREADS
-static struct eh_context *eh_context_specific ();
-#endif
-
-static struct eh_context *(*get_eh_context) () = &eh_context_initialize;
-
-/* Routine to get EH context.
- This one will simply call the function pointer. */
-
-void *
-__get_eh_context ()
-{
- return (void *) (*get_eh_context) ();
-}
-
-/* Get and set the language specific info pointer. */
-
-void **
-__get_eh_info ()
-{
- struct eh_context *eh = (*get_eh_context) ();
- return &eh->info;
-}
-\f
-#ifdef DWARF2_UNWIND_INFO
-static int dwarf_reg_size_table_initialized = 0;
-static char dwarf_reg_size_table[FIRST_PSEUDO_REGISTER];
-
-static void
-init_reg_size_table ()
-{
- __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
- dwarf_reg_size_table_initialized = 1;
-}
-#endif
-
-#if __GTHREADS
-static void
-eh_threads_initialize ()
-{
- /* Try to create the key. If it fails, revert to static method,
- otherwise start using thread specific EH contexts. */
- if (__gthread_key_create (&eh_context_key, &eh_context_free) == 0)
- get_eh_context = &eh_context_specific;
- else
- get_eh_context = &eh_context_static;
-}
-#endif /* no __GTHREADS */
-
-/* Initialize EH context.
- This will be called only once, since we change GET_EH_CONTEXT
- pointer to another routine. */
-
-static struct eh_context *
-eh_context_initialize ()
-{
-#if __GTHREADS
-
- static __gthread_once_t once = __GTHREAD_ONCE_INIT;
- /* Make sure that get_eh_context does not point to us anymore.
- Some systems have dummy thread routines in their libc that
- return a success (Solaris 2.6 for example). */
- if (__gthread_once (&once, eh_threads_initialize) != 0
- || get_eh_context == &eh_context_initialize)
- {
- /* Use static version of EH context. */
- get_eh_context = &eh_context_static;
- }
-#ifdef DWARF2_UNWIND_INFO
- {
- static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
- if (__gthread_once (&once_regsizes, init_reg_size_table) != 0
- || ! dwarf_reg_size_table_initialized)
- init_reg_size_table ();
- }
-#endif
-
-#else /* no __GTHREADS */
-
- /* Use static version of EH context. */
- get_eh_context = &eh_context_static;
-
-#ifdef DWARF2_UNWIND_INFO
- init_reg_size_table ();
-#endif
-
-#endif /* no __GTHREADS */
-
- return (*get_eh_context) ();
-}
-
-/* Return a static EH context. */
-
-static struct eh_context *
-eh_context_static ()
-{
- static struct eh_context eh;
- static int initialized;
- static void *top_elt[2];
-
- if (! initialized)
- {
- initialized = 1;
- memset (&eh, 0, sizeof eh);
- eh.dynamic_handler_chain = top_elt;
- }
- return &eh;
-}
-
-#if __GTHREADS
-/* Return a thread specific EH context. */
-
-static struct eh_context *
-eh_context_specific ()
-{
- struct eh_context *eh;
- eh = (struct eh_context *) __gthread_getspecific (eh_context_key);
- if (! eh)
- {
- eh = new_eh_context ();
- if (__gthread_setspecific (eh_context_key, (void *) eh) != 0)
- __terminate ();
- }
-
- return eh;
-}
-#endif __GTHREADS
-\f
-/* Support routines for setjmp/longjmp exception handling. */
-
-/* Calls to __sjthrow are generated by the compiler when an exception
- is raised when using the setjmp/longjmp exception handling codegen
- method. */
-
-#ifdef DONT_USE_BUILTIN_SETJMP
-extern void longjmp (void *, int);
-#endif
-
-/* Routine to get the head of the current thread's dynamic handler chain
- use for exception handling. */
-
-void ***
-__get_dynamic_handler_chain ()
-{
- struct eh_context *eh = (*get_eh_context) ();
- return &eh->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. 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. */
-
-extern void __sjthrow (void) __attribute__ ((__noreturn__));
-
-void
-__sjthrow ()
-{
- struct eh_context *eh = (*get_eh_context) ();
- void ***dhc = &eh->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->info || (*dhc)[0] == 0)
- __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. */
-
-extern void __sjpopnthrow (void) __attribute__ ((__noreturn__));
-
-void
-__sjpopnthrow ()
-{
- struct eh_context *eh = (*get_eh_context) ();
- void ***dhc = &eh->dynamic_handler_chain;
- 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 ();
-}
-\f
-/* Support code for all exception region-based exception handling. */
-
-int
-__eh_rtime_match (void *rtime)
-{
- void *info;
- __eh_matcher matcher;
- void *ret;
-
- info = *(__get_eh_info ());
- matcher = ((__eh_info *)info)->match_function;
- if (! matcher)
- {
-#ifndef inhibit_libc
- fprintf (stderr, "Internal Compiler Bug: No runtime type matcher.");
-#endif
- return 0;
- }
- ret = (*matcher) (info, rtime, (void *)0);
- return (ret != NULL);
-}
-
-/* This value identifies the place from which an exception is being
- thrown. */
-
-#ifdef EH_TABLE_LOOKUP
-
-EH_TABLE_LOOKUP
-
-#else
-
-#ifdef DWARF2_UNWIND_INFO
-
-/* Return the table version of an exception descriptor */
-
-short
-__get_eh_table_version (exception_descriptor *table)
-{
- return table->lang.version;
-}
-
-/* Return the originating table language of an exception descriptor */
-
-short
-__get_eh_table_language (exception_descriptor *table)
-{
- return table->lang.language;
-}