forked from M-Labs/artiq
Implement __artiq_personality.
This commit is contained in:
parent
bb5fe60137
commit
7c77dd317a
|
@ -979,10 +979,16 @@ class Raise(Terminator):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
:param value: (:class:`Value`) exception value
|
:param value: (:class:`Value`) exception value
|
||||||
|
:param exn: (:class:`BasicBlock`) exceptional target
|
||||||
"""
|
"""
|
||||||
def __init__(self, value, name=""):
|
def __init__(self, value, exn=None, name=""):
|
||||||
assert isinstance(value, Value)
|
assert isinstance(value, Value)
|
||||||
super().__init__([value], builtins.TNone(), name)
|
if exn is not None:
|
||||||
|
assert isinstance(exn, BasicBlock)
|
||||||
|
operands = [value, exn]
|
||||||
|
else:
|
||||||
|
operands = [value]
|
||||||
|
super().__init__(operands, builtins.TNone(), name)
|
||||||
|
|
||||||
def opcode(self):
|
def opcode(self):
|
||||||
return "raise"
|
return "raise"
|
||||||
|
@ -990,6 +996,9 @@ class Raise(Terminator):
|
||||||
def value(self):
|
def value(self):
|
||||||
return self.operands[0]
|
return self.operands[0]
|
||||||
|
|
||||||
|
def exception_target(self):
|
||||||
|
return self.operands[1]
|
||||||
|
|
||||||
class Invoke(Terminator):
|
class Invoke(Terminator):
|
||||||
"""
|
"""
|
||||||
A function call operation that supports exception handling.
|
A function call operation that supports exception handling.
|
||||||
|
|
|
@ -472,7 +472,10 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||||
self.append(ir.SetAttr(exn, "__file__", loc_file))
|
self.append(ir.SetAttr(exn, "__file__", loc_file))
|
||||||
self.append(ir.SetAttr(exn, "__line__", loc_line))
|
self.append(ir.SetAttr(exn, "__line__", loc_line))
|
||||||
self.append(ir.SetAttr(exn, "__col__", loc_column))
|
self.append(ir.SetAttr(exn, "__col__", loc_column))
|
||||||
self.append(ir.Raise(exn))
|
if self.unwind_target:
|
||||||
|
self.append(ir.Raise(exn, self.unwind_target))
|
||||||
|
else:
|
||||||
|
self.append(ir.Raise(exn))
|
||||||
|
|
||||||
def visit_Raise(self, node):
|
def visit_Raise(self, node):
|
||||||
self.raise_exn(self.visit(node.exc))
|
self.raise_exn(self.visit(node.exc))
|
||||||
|
|
|
@ -582,17 +582,30 @@ class LLVMIRGenerator:
|
||||||
return self.llbuilder.unreachable()
|
return self.llbuilder.unreachable()
|
||||||
|
|
||||||
def process_Raise(self, insn):
|
def process_Raise(self, insn):
|
||||||
arg = self.map(insn.operands[0])
|
llexn = self.map(insn.value())
|
||||||
llinsn = self.llbuilder.call(self.llbuiltin("__artiq_raise"), [arg],
|
if insn.exception_target() is not None:
|
||||||
name=insn.name)
|
llnormalblock = self.llfunction.append_basic_block("unreachable")
|
||||||
|
llnormalblock.terminator = ll.Unreachable(llnormalblock)
|
||||||
|
llnormalblock.instructions.append(llnormalblock.terminator)
|
||||||
|
|
||||||
|
llunwindblock = self.map(insn.exception_target())
|
||||||
|
llinsn = self.llbuilder.invoke(self.llbuiltin("__artiq_raise"), [llexn],
|
||||||
|
llnormalblock, llunwindblock,
|
||||||
|
name=insn.name)
|
||||||
|
else:
|
||||||
|
llinsn = self.llbuilder.call(self.llbuiltin("__artiq_raise"), [llexn],
|
||||||
|
name=insn.name)
|
||||||
|
self.llbuilder.unreachable()
|
||||||
llinsn.attributes.add('noreturn')
|
llinsn.attributes.add('noreturn')
|
||||||
self.llbuilder.unreachable()
|
|
||||||
return llinsn
|
return llinsn
|
||||||
|
|
||||||
def process_LandingPad(self, insn):
|
def process_LandingPad(self, insn):
|
||||||
lllandingpad = self.llbuilder.landingpad(ll.LiteralStructType([ll.IntType(8).as_pointer()]),
|
# Layout on return from landing pad: {%_Unwind_Exception*, %Exception*}
|
||||||
|
lllandingpadty = ll.LiteralStructType([ll.IntType(8).as_pointer(),
|
||||||
|
ll.IntType(8).as_pointer()])
|
||||||
|
lllandingpad = self.llbuilder.landingpad(lllandingpadty,
|
||||||
self.llbuiltin("__artiq_personality"))
|
self.llbuiltin("__artiq_personality"))
|
||||||
llrawexn = self.llbuilder.extract_value(lllandingpad, 0)
|
llrawexn = self.llbuilder.extract_value(lllandingpad, 1)
|
||||||
llexn = self.llbuilder.bitcast(llrawexn, self.llty_of_type(insn.type))
|
llexn = self.llbuilder.bitcast(llrawexn, self.llty_of_type(insn.type))
|
||||||
llexnnameptr = self.llbuilder.gep(llexn, [self.llindex(0), self.llindex(0)])
|
llexnnameptr = self.llbuilder.gep(llexn, [self.llindex(0), self.llindex(0)])
|
||||||
llexnname = self.llbuilder.load(llexnnameptr)
|
llexnname = self.llbuilder.load(llexnnameptr)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
CC ?= clang
|
CC ?= clang
|
||||||
|
|
||||||
libartiq_personality.so: ../../soc/runtime/artiq_personality.c artiq_terminate.c
|
libartiq_personality.so: ../../soc/runtime/artiq_personality.c artiq_terminate.c
|
||||||
$(CC) -Wall -Werror -I. -I../../soc/runtime -fPIC -shared -o $@ $^
|
$(CC) -Wall -Werror -I. -I../../soc/runtime -g -fPIC -shared -o $@ $^
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
void __artiq_terminate(struct artiq_exception *exn) {
|
void __artiq_terminate(struct artiq_exception *exn) {
|
||||||
printf("Uncaught %s: %s (%"PRIi64", %"PRIi64", %"PRIi64")\n"
|
printf("Uncaught %s: %s (%"PRIi64", %"PRIi64", %"PRIi64")\n"
|
||||||
"at %s:%"PRIi32":%"PRIi32"",
|
"at %s:%"PRIi32":%"PRIi32"\n",
|
||||||
exn->name, exn->message,
|
exn->name, exn->message,
|
||||||
exn->param[0], exn->param[1], exn->param[1],
|
exn->param[0], exn->param[1], exn->param[1],
|
||||||
exn->file, exn->line, exn->column + 1);
|
exn->file, exn->line, exn->column + 1);
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
# RUN: %python -m artiq.compiler.testbench.jit %s
|
||||||
|
# REQUIRES: exceptions
|
||||||
|
|
||||||
|
try:
|
||||||
|
1/0
|
||||||
|
except ZeroDivisionError:
|
||||||
|
# CHECK-L: OK
|
||||||
|
print("OK")
|
|
@ -5,6 +5,198 @@
|
||||||
#include <unwind.h>
|
#include <unwind.h>
|
||||||
#include "artiq_personality.h"
|
#include "artiq_personality.h"
|
||||||
|
|
||||||
|
/* Logging */
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define EH_LOG0(fmt) fprintf(stderr, "__artiq_personality: " fmt "\n")
|
||||||
|
#define EH_LOG(fmt, ...) fprintf(stderr, "__artiq_personality: " fmt "\n", __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define EH_LOG0(fmt)
|
||||||
|
#define EH_LOG(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define EH_FAIL(err) \
|
||||||
|
do { \
|
||||||
|
fprintf(stderr, "__artiq_personality fatal: %s\n", err); \
|
||||||
|
abort(); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define EH_ASSERT(expr) \
|
||||||
|
if(!(expr)) EH_FAIL(#expr)
|
||||||
|
|
||||||
|
/* DWARF format handling */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DW_EH_PE_absptr = 0x00,
|
||||||
|
DW_EH_PE_uleb128 = 0x01,
|
||||||
|
DW_EH_PE_udata2 = 0x02,
|
||||||
|
DW_EH_PE_udata4 = 0x03,
|
||||||
|
DW_EH_PE_udata8 = 0x04,
|
||||||
|
DW_EH_PE_sleb128 = 0x09,
|
||||||
|
DW_EH_PE_sdata2 = 0x0A,
|
||||||
|
DW_EH_PE_sdata4 = 0x0B,
|
||||||
|
DW_EH_PE_sdata8 = 0x0C,
|
||||||
|
DW_EH_PE_pcrel = 0x10,
|
||||||
|
DW_EH_PE_textrel = 0x20,
|
||||||
|
DW_EH_PE_datarel = 0x30,
|
||||||
|
DW_EH_PE_funcrel = 0x40,
|
||||||
|
DW_EH_PE_aligned = 0x50,
|
||||||
|
DW_EH_PE_indirect = 0x80,
|
||||||
|
DW_EH_PE_omit = 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read a uleb128 encoded value and advance pointer
|
||||||
|
// See Variable Length Data in: http://dwarfstd.org/Dwarf3.pdf
|
||||||
|
static uintptr_t readULEB128(const uint8_t **data) {
|
||||||
|
uintptr_t result = 0;
|
||||||
|
uintptr_t shift = 0;
|
||||||
|
unsigned char byte;
|
||||||
|
const uint8_t *p = *data;
|
||||||
|
|
||||||
|
do {
|
||||||
|
byte = *p++;
|
||||||
|
result |= (byte & 0x7f) << shift;
|
||||||
|
shift += 7;
|
||||||
|
}
|
||||||
|
while (byte & 0x80);
|
||||||
|
|
||||||
|
*data = p;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read a sleb128 encoded value and advance pointer
|
||||||
|
// See Variable Length Data in: http://dwarfstd.org/Dwarf3.pdf
|
||||||
|
static uintptr_t readSLEB128(const uint8_t **data) {
|
||||||
|
uintptr_t result = 0;
|
||||||
|
uintptr_t shift = 0;
|
||||||
|
unsigned char byte;
|
||||||
|
const uint8_t *p = *data;
|
||||||
|
|
||||||
|
do {
|
||||||
|
byte = *p++;
|
||||||
|
result |= (byte & 0x7f) << shift;
|
||||||
|
shift += 7;
|
||||||
|
}
|
||||||
|
while (byte & 0x80);
|
||||||
|
|
||||||
|
*data = p;
|
||||||
|
|
||||||
|
if ((byte & 0x40) && (shift < (sizeof(result) << 3))) {
|
||||||
|
result |= (~0 << shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned getEncodingSize(uint8_t Encoding) {
|
||||||
|
if (Encoding == DW_EH_PE_omit)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (Encoding & 0x0F) {
|
||||||
|
case DW_EH_PE_absptr:
|
||||||
|
return sizeof(uintptr_t);
|
||||||
|
case DW_EH_PE_udata2:
|
||||||
|
return sizeof(uint16_t);
|
||||||
|
case DW_EH_PE_udata4:
|
||||||
|
return sizeof(uint32_t);
|
||||||
|
case DW_EH_PE_udata8:
|
||||||
|
return sizeof(uint64_t);
|
||||||
|
case DW_EH_PE_sdata2:
|
||||||
|
return sizeof(int16_t);
|
||||||
|
case DW_EH_PE_sdata4:
|
||||||
|
return sizeof(int32_t);
|
||||||
|
case DW_EH_PE_sdata8:
|
||||||
|
return sizeof(int64_t);
|
||||||
|
default:
|
||||||
|
// not supported
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read a pointer encoded value and advance pointer
|
||||||
|
// See Variable Length Data in: http://dwarfstd.org/Dwarf3.pdf
|
||||||
|
static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
|
||||||
|
uintptr_t result = 0;
|
||||||
|
const uint8_t *p = *data;
|
||||||
|
|
||||||
|
if (encoding == DW_EH_PE_omit)
|
||||||
|
return(result);
|
||||||
|
|
||||||
|
// first get value
|
||||||
|
switch (encoding & 0x0F) {
|
||||||
|
case DW_EH_PE_absptr:
|
||||||
|
result = *((uintptr_t*)p);
|
||||||
|
p += sizeof(uintptr_t);
|
||||||
|
break;
|
||||||
|
case DW_EH_PE_uleb128:
|
||||||
|
result = readULEB128(&p);
|
||||||
|
break;
|
||||||
|
// Note: This case has not been tested
|
||||||
|
case DW_EH_PE_sleb128:
|
||||||
|
result = readSLEB128(&p);
|
||||||
|
break;
|
||||||
|
case DW_EH_PE_udata2:
|
||||||
|
result = *((uint16_t*)p);
|
||||||
|
p += sizeof(uint16_t);
|
||||||
|
break;
|
||||||
|
case DW_EH_PE_udata4:
|
||||||
|
result = *((uint32_t*)p);
|
||||||
|
p += sizeof(uint32_t);
|
||||||
|
break;
|
||||||
|
case DW_EH_PE_udata8:
|
||||||
|
result = *((uint64_t*)p);
|
||||||
|
p += sizeof(uint64_t);
|
||||||
|
break;
|
||||||
|
case DW_EH_PE_sdata2:
|
||||||
|
result = *((int16_t*)p);
|
||||||
|
p += sizeof(int16_t);
|
||||||
|
break;
|
||||||
|
case DW_EH_PE_sdata4:
|
||||||
|
result = *((int32_t*)p);
|
||||||
|
p += sizeof(int32_t);
|
||||||
|
break;
|
||||||
|
case DW_EH_PE_sdata8:
|
||||||
|
result = *((int64_t*)p);
|
||||||
|
p += sizeof(int64_t);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// not supported
|
||||||
|
abort();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// then add relative offset
|
||||||
|
switch (encoding & 0x70) {
|
||||||
|
case DW_EH_PE_absptr:
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
|
case DW_EH_PE_pcrel:
|
||||||
|
result += (uintptr_t)(*data);
|
||||||
|
break;
|
||||||
|
case DW_EH_PE_textrel:
|
||||||
|
case DW_EH_PE_datarel:
|
||||||
|
case DW_EH_PE_funcrel:
|
||||||
|
case DW_EH_PE_aligned:
|
||||||
|
default:
|
||||||
|
// not supported
|
||||||
|
abort();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// then apply indirection
|
||||||
|
if (encoding & DW_EH_PE_indirect) {
|
||||||
|
result = *((uintptr_t*)result);
|
||||||
|
}
|
||||||
|
|
||||||
|
*data = p;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Raising and catching */
|
||||||
|
|
||||||
#define ARTIQ_EXCEPTION_CLASS 0x4152545141525451LL // 'ARTQARTQ'
|
#define ARTIQ_EXCEPTION_CLASS 0x4152545141525451LL // 'ARTQARTQ'
|
||||||
|
|
||||||
struct artiq_raised_exception {
|
struct artiq_raised_exception {
|
||||||
|
@ -37,5 +229,140 @@ void __artiq_raise(struct artiq_exception *artiq_exn) {
|
||||||
_Unwind_Reason_Code __artiq_personality(
|
_Unwind_Reason_Code __artiq_personality(
|
||||||
int version, _Unwind_Action actions, uint64_t exceptionClass,
|
int version, _Unwind_Action actions, uint64_t exceptionClass,
|
||||||
struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context) {
|
struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context) {
|
||||||
abort();
|
EH_LOG("entry (actions =%s%s%s%s; class=%08lx; object=%p, context=%p)",
|
||||||
|
(actions & _UA_SEARCH_PHASE ? " search" : ""),
|
||||||
|
(actions & _UA_CLEANUP_PHASE ? " cleanup" : ""),
|
||||||
|
(actions & _UA_HANDLER_FRAME ? " handler" : ""),
|
||||||
|
(actions & _UA_FORCE_UNWIND ? " force-unwind" : ""),
|
||||||
|
exceptionClass, exceptionObject, context);
|
||||||
|
EH_ASSERT((exceptionClass == ARTIQ_EXCEPTION_CLASS) &&
|
||||||
|
"Foreign exceptions are not supported");
|
||||||
|
|
||||||
|
struct artiq_raised_exception *inflight =
|
||||||
|
(struct artiq_raised_exception*)exceptionObject;
|
||||||
|
EH_LOG("exception name=%s",
|
||||||
|
inflight->artiq.name);
|
||||||
|
|
||||||
|
// Get a pointer to LSDA. If there's no LSDA, this function doesn't
|
||||||
|
// actually handle any exceptions.
|
||||||
|
const uint8_t *lsda = (const uint8_t*) _Unwind_GetLanguageSpecificData(context);
|
||||||
|
if(lsda == NULL)
|
||||||
|
return _URC_CONTINUE_UNWIND;
|
||||||
|
|
||||||
|
EH_LOG("lsda=%p", lsda);
|
||||||
|
|
||||||
|
// Get the current instruction pointer and offset it before next
|
||||||
|
// instruction in the current frame which threw the exception.
|
||||||
|
uintptr_t pc = _Unwind_GetIP(context) - 1;
|
||||||
|
|
||||||
|
// Get beginning of the current frame's code.
|
||||||
|
uintptr_t funcStart = _Unwind_GetRegionStart(context);
|
||||||
|
uintptr_t pcOffset = pc - funcStart;
|
||||||
|
|
||||||
|
EH_LOG("pc=%p (%p+%p)", (void*)pc, (void*)funcStart, (void*)pcOffset);
|
||||||
|
|
||||||
|
// Parse LSDA header.
|
||||||
|
uint8_t lpStartEncoding = *lsda++;
|
||||||
|
if (lpStartEncoding != DW_EH_PE_omit) {
|
||||||
|
readEncodedPointer(&lsda, lpStartEncoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ttypeEncoding = *lsda++;
|
||||||
|
const uint8_t *classInfo = NULL;
|
||||||
|
if (ttypeEncoding != DW_EH_PE_omit) {
|
||||||
|
// Calculate type info locations in emitted dwarf code which
|
||||||
|
// were flagged by type info arguments to llvm.eh.selector
|
||||||
|
// intrinsic
|
||||||
|
uintptr_t classInfoOffset = readULEB128(&lsda);
|
||||||
|
classInfo = lsda + classInfoOffset;
|
||||||
|
EH_LOG("classInfo=%p", classInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk call-site table looking for range that includes current PC.
|
||||||
|
uint8_t callSiteEncoding = *lsda++;
|
||||||
|
uint32_t callSiteTableLength = readULEB128(&lsda);
|
||||||
|
const uint8_t *callSiteTableStart = lsda;
|
||||||
|
const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength;
|
||||||
|
const uint8_t *actionTableStart = callSiteTableEnd;
|
||||||
|
const uint8_t *callSitePtr = callSiteTableStart;
|
||||||
|
|
||||||
|
while (callSitePtr < callSiteTableEnd) {
|
||||||
|
uintptr_t start = readEncodedPointer(&callSitePtr,
|
||||||
|
callSiteEncoding);
|
||||||
|
uintptr_t length = readEncodedPointer(&callSitePtr,
|
||||||
|
callSiteEncoding);
|
||||||
|
uintptr_t landingPad = readEncodedPointer(&callSitePtr,
|
||||||
|
callSiteEncoding);
|
||||||
|
uintptr_t actionValue = readULEB128(&callSitePtr);
|
||||||
|
|
||||||
|
EH_LOG("call site (start=+%p, len=%d, landingPad=+%p, actionValue=%d)",
|
||||||
|
(void*)start, (int)length, (void*)landingPad, (int)actionValue);
|
||||||
|
|
||||||
|
if(landingPad == 0) {
|
||||||
|
EH_LOG0("no landing pad, skipping");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((start <= pcOffset) && (pcOffset < (start + length))) {
|
||||||
|
EH_LOG0("call site matches pc");
|
||||||
|
|
||||||
|
int exceptionMatched = 0;
|
||||||
|
if(actionValue) {
|
||||||
|
const uint8_t *actionEntry = actionTableStart + (actionValue - 1);
|
||||||
|
EH_LOG("actionEntry=%p", actionEntry);
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
// Each emitted DWARF action corresponds to a 2 tuple of
|
||||||
|
// type info address offset, and action offset to the next
|
||||||
|
// emitted action.
|
||||||
|
intptr_t typeInfoOffset = readSLEB128(&actionEntry);
|
||||||
|
const uint8_t *tempActionEntry = actionEntry;
|
||||||
|
intptr_t actionOffset = readSLEB128(&tempActionEntry);
|
||||||
|
EH_LOG("typeInfoOffset=%p actionOffset=%p",
|
||||||
|
(void*)typeInfoOffset, (void*)actionOffset);
|
||||||
|
EH_ASSERT((typeInfoOffset >= 0) && "Filter clauses are not supported");
|
||||||
|
|
||||||
|
unsigned encodingSize = getEncodingSize(ttypeEncoding);
|
||||||
|
const uint8_t *typeInfoPtrPtr = classInfo - typeInfoOffset * encodingSize;
|
||||||
|
uintptr_t typeInfoPtr = readEncodedPointer(&typeInfoPtrPtr, ttypeEncoding);
|
||||||
|
EH_LOG("encodingSize=%u typeInfoPtrPtr=%p typeInfoPtr=%p",
|
||||||
|
encodingSize, typeInfoPtrPtr, (void*)typeInfoPtr);
|
||||||
|
EH_LOG("typeInfo=%s", (char*)typeInfoPtr);
|
||||||
|
|
||||||
|
if(inflight->artiq.typeinfo == typeInfoPtr) {
|
||||||
|
EH_LOG0("matching action found");
|
||||||
|
exceptionMatched = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!actionOffset)
|
||||||
|
break;
|
||||||
|
|
||||||
|
actionEntry += actionOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(actions & _UA_SEARCH_PHASE)) {
|
||||||
|
EH_LOG0("jumping to landing pad");
|
||||||
|
|
||||||
|
_Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
|
||||||
|
(uintptr_t)exceptionObject);
|
||||||
|
_Unwind_SetGR(context, __builtin_eh_return_data_regno(1),
|
||||||
|
(uintptr_t)&inflight->artiq);
|
||||||
|
_Unwind_SetIP(context, funcStart + landingPad);
|
||||||
|
|
||||||
|
return _URC_INSTALL_CONTEXT;
|
||||||
|
} else if(exceptionMatched) {
|
||||||
|
EH_LOG0("handler found");
|
||||||
|
|
||||||
|
return _URC_HANDLER_FOUND;
|
||||||
|
} else {
|
||||||
|
EH_LOG0("handler not found");
|
||||||
|
|
||||||
|
return _URC_CONTINUE_UNWIND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _URC_CONTINUE_UNWIND;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
struct artiq_exception {
|
struct artiq_exception {
|
||||||
union {
|
union {
|
||||||
void *typeinfo;
|
uintptr_t typeinfo;
|
||||||
const char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
const char *file;
|
const char *file;
|
||||||
|
|
Loading…
Reference in New Issue