// Reference to all sorts of information for exception handling.

// C++ Interface to exception handlers.

void * __cxa_allocate_exception(size_t thrown_size);
// Creates space for the exception.

void __cxa_free_exception(void * thrown_exception);

void __cxa_throw(void * thrown_exception, struct type_info * tinfo,
		void (*dest)(void*));
// Throws the exception, is not supposed to return but ours should,
// to handle resumption exceptions.

void __cxa_begin_catch(); -> void * __cxa_begin_catch(void * exceptionObject);
void __cxa_end_catch();
// Not sure, beginning and end of catch block maybe?


/* Unwind Module
 * Full list: https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
 * Avaible at: /usr/lib/gcc/x86_64-linux-gnu/{5}/include/unwind.h
 */

typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)
     (int, _Unwind_Action, _Unwind_Exception_Class,
      struct _Unwind_Exception *, struct _Unwind_Context *);
/* Type of the personality function, which does not have a set name.
 *   So far `__gcfa_personality_v0` has been used.
 * Called by _Unwind_RaiseException (called by __cxa_throw)
 *   or by _Unwind_ForcedUnwind's personality wrapper.
 * Params:
 *   int version: Repersents unwind convention standard.
 *   _Unwind_Action actions: Set of actions, used as instructions.
 *   _Unwind_Exception_Class: 8-byte identifer: high 4 vendor, low 4 language.
 *   _Unwind_Exception unwind_exception: Pointer to exception data.
 *   _Unwind_Context context: Information on the current stack frame.
 * Return:
 *   _Unwind_Reason_Code: Requests an action from the unwinder.
 */


// _Unwind_Action flags (multiple may be set):
_UA_SEARCH_PHASE  // Seaching for the handler
_UA_CLEANUP_PHASE // Cleanup until handler found.
_UA_HANDLER_FRAME // Previous search found handler here.
_UA_FORCE_UNWIND  // Unwind, do not decide if we have reached the handler.
_UA_END_OF_STACK  // We have reached the end of the stack.


// _Unwind_Reason_Code values (one may be selected):
_URC_NO_REASON          // Containues force unwind.
_URC_FOREIGN_EXCEPTION_CAUGHT // Cross between runtime environments.
_URC_FATAL_PHASE2_ERROR // Error in cleanup, not otherwise defined. (Rare?)
_URC_FATAL_PHASE1_ERROR // Error in search, not otherwise defined.
_URC_NORMAL_STOP
_URC_END_OF_STACK       // eos found before a handler.
_URC_HANDLER_FOUND      // Just the signal (search?)
_URC_INSTALL_CONTEXT    // Handler found, resume execution (cleanup?)
_URC_CONTINUE_UNWIND    // No handler found (search&cleanup)


// Exception Header: (?)
typedef void (*_Unwind_Exception_Cleanup_Fn)
		(_Unwind_Reason_Code reason, struct _Unwind_Exception *exc);

struct _Unwind_Exception {
	uint64 exception_class;
	_Unwind_Exception_Cleanup_Fn exception_cleanup;
	uint64 private_1; // Do not access.
	uint64 private_2; // Do not access.
};


// There are two functions to access the unwind "operation".
// The standard exception handler, uses the personality function.
_Unwind_Reason_Code _Unwind_RaiseException(
	struct _Unwind_Exception * exception_object);

// Helper for force unwind.
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)(
	int version,
	_Unwind_Action actions,
	uint64 exceptionClass,
	struct _Unwind_Exception * exceptionObject,
	struct _Unwind_Context * context,
	void * stop_parameter);

// Special unwinder, wraps the personality function.
_Unwind_Reason_Code _Unwind_ForcedUnwind(
	struct _Unwind_Exception * exception_object,
	_Unwind_Stop_Fn stop,
	void * stop_parameter);

// Continues unwinding
void _Unwind_Resume(struct _Unwind_Exception * exception_object);
// Seems to be for finally and deconstrctors, not so much rethrow.
// However I haven't figured out the difference.


/* _Unwind Helper functions:
 *
 * _Unwind_GetLanguageSpecificData - LSDA (destructors and landing pads)
 * _Unwind_GetRegionStart - Function pointer to current stack frame.
 * _Unwind_GetIP - Get frame's instruction pointer
 *   This might be the actual function pointer or the call site up stack.
 *
 * All three have the same signature. */
uint64 _Unwind_Get*(struct _Unwind_Context * context);

void _Unwind_SetIP(struct _Unwind_Context * context, uint64 new_value);
uint64 _Unwind_GetGR(struct _Unwind_Context * context, int index);
void _Unwind_SetGR(struct _Unwind_Context * <>, int index, uint64 <>);
// __builtin_eh_return_data_regno(^) ^=[0..3]? gives index.

// Locally we also seem to have:
_Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);

// GCC (Dwarf2 ?) Frame Layout Macros
// See: https://gcc.gnu.org/onlinedocs/gccint/Frame-Layout.html
// Include from: ???

FIRST_PARAM_OFFSET(fundecl)
// Offset from argument pointer to first arguments address, or above that
// address if ARGS_GROW_DOWNWARD.

ARG_POINTER_CFA_OFFSET(fundecl)
// Default: FIRST_PARM_OFFSET(fundecl) + crtl->args.pretend_args_size
