#define TI_NO_SRCPOS
#include "backend.h"
#include <assert.h>
#include <stdio.h>
#include <backend-defines.h>
/* #include <tic-am2/tic.h> */
#include "static-global.h"
#include "exceptions.h"
#include "native-utils.h"
#include "subtype.h"
#include "gp-type.h"

/*
 * Note: if titanium ever grows threads, each
 * thread must have its own copy of this global.
 * DONE - abegel
 */

TI_EXNSTATE_ALIGN ti_ExceptionState *PERPROC_DEF(exception_state);


int find_handler( const ti_ExceptionState * const state,
		  const struct class_header * const catchers[] )
{
    if (!state->handling) {
	int candidate;
	for (candidate = 0; catchers[ candidate ]; ++candidate)
	    if (instanceOfClass( state->value, catchers[ candidate ] ))
		return candidate;
    }
    
    return NO_HANDLER;
}

struct T9Throwable4lang4java;
typedef struct T9Throwable4lang4java T9Throwable4lang4java;
typedef GP_type(T9Throwable4lang4java) GP_T9Throwable4lang4java;
extern void m13dumpExceptionPT9Throwable4lang4javamT11NativeUtils4lang2ti(GP_T9Throwable4lang4java);
extern void printExitStats(int sglobal);

void toss( const GP_instance exception )
{
    ti_ExceptionState *state = PERPROC_REF(exception_state);
    CHECK_NULL_GLOBAL_IFBC( exception, "while throwing exception" );
    
    if (!state) {
	GP_T9Throwable4lang4java exn;
	fputs( "fatal error: uncaught exception", stderr );
        fprintf(stderr, " on processor %i:\n", MYPROC);
        fflush(stderr);
	/* dump the exn to stderr */
        exn = *(GP_T9Throwable4lang4java*)&(exception);
        m13dumpExceptionPT9Throwable4lang4javamT11NativeUtils4lang2ti(exn);
        fflush(stderr);
        printExitStats(0);
        fflush(stderr);
	abort();
    }
    
#if defined(linux) && defined(i386)
#ifdef __GLIBC__
    assert( state->handler[0].__jmpbuf[ JB_BP ] );
    assert( state->handler[0].__jmpbuf[ JB_SP ] );
    assert( state->handler[0].__jmpbuf[ JB_PC ] );
#else  /* Linux, old libc */
    assert( state->handler[0].__bp );
    assert( state->handler[0].__sp );
    assert( state->handler[0].__pc );
#endif /* Linux, old libc */
#else  /* not Linux */
    /* add other system-specific tests for reasonable jmp_buf */
#endif /* not Linux */
    
    state->value = exception;
    LONGJMP( state->handler, 1 );
}