void pushdefer(struct Func f) { struct Defer *d = (struct Defer*)malloc(sizeof(struct Defer)); d->f = f; d->caller = runtime_caller_region(1); d->next = tlsdefer; tlsdefer = d; }
struct Eface recover(int32_t indirect) { // (valid) call stack: // recover // deferred function // <deferred function wrapper> // callniladic // guardedcall0 // run_defers // catch-site struct Eface value; int depth = 5 + (indirect ? 1 : 0); int i; if (tlspanic && tlsdefers && tlsdefers->caller == runtime_caller_region(depth)) { struct Panic *p = tlspanic; struct Eface value = p->value; while (tlspanic) { p = tlspanic->next; free(tlspanic); tlspanic = p; } return value; } else { value.type = value.data = (void*)0; return value; } }
void rundefers(void) { // FIXME cater for recursive calls. const uintptr_t caller = runtime_caller_region(1); for (; tlsdefer && tlsdefer->caller == caller;) { struct Defer *d = tlsdefer; guardedcall(d->f); tlsdefer = tlsdefer->next; free(d); } if (tlspanic) { __cxa_throw(__cxa_allocate_exception(0), &_ZTI5Eface, NULL); } }
void recover(int32_t indirect, struct Eface *error) { // (valid) call stack: // recover // deferred function // <deferred function wrapper> // callniladic // guardedcall // run_defers // catch-site int depth = 5 + (indirect ? 1 : 0); if (tlspanic && tlsdefer && tlsdefer->caller == runtime_caller_region(depth)) { struct Panic *p = tlspanic; memcpy(error, &p->value, sizeof(struct Eface)); while (tlspanic) { p = tlspanic->next; free(tlspanic); tlspanic = p; } return; } memset(error, 0, sizeof(struct Eface)); }
void initdefers(struct Defers *d) { d->caller = runtime_caller_region(1); d->d = NULL; d->next = tlsdefers; tlsdefers = d; }