Implement exception raising.

This commit is contained in:
whitequark 2015-07-27 05:46:43 +03:00
parent ef4a06a270
commit bb5fe60137
7 changed files with 86 additions and 17 deletions

View File

@ -1,4 +1,4 @@
CC ?= clang CC ?= clang
libartiq_personality.so: ../../soc/runtime/artiq_personality.c libartiq_personality.so: ../../soc/runtime/artiq_personality.c artiq_terminate.c
$(CC) -Wall -Werror -I. -fPIC -shared -o $@ $< $(CC) -Wall -Werror -I. -I../../soc/runtime -fPIC -shared -o $@ $^

View File

@ -0,0 +1,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <unwind.h>
#include <artiq_personality.h>
void __artiq_terminate(struct artiq_exception *exn) {
printf("Uncaught %s: %s (%"PRIi64", %"PRIi64", %"PRIi64")\n"
"at %s:%"PRIi32":%"PRIi32"",
exn->name, exn->message,
exn->param[0], exn->param[1], exn->param[1],
exn->file, exn->line, exn->column + 1);
exit(1);
}

2
lit-test/not.py Normal file
View File

@ -0,0 +1,2 @@
import sys, subprocess
exit(not subprocess.call(sys.argv[1:]))

View File

@ -1,4 +1,6 @@
# RUN: %python -m artiq.compiler.testbench.jit %s # RUN: %not %python -m artiq.compiler.testbench.jit %s
# REQUIRES: exceptions # REQUIRES: exceptions
# CHECK-L: Uncaught ZeroDivisionError: cannot divide by zero (0, 0, 0)
# CHECK-L: at input.py:${LINE:+1}:0
1/0 1/0

View File

@ -9,9 +9,13 @@ config.test_format = lit.formats.ShTest()
config.suffixes = ['.py'] config.suffixes = ['.py']
python_executable = 'python3' python_executable = 'python3'
harness = '{} {}'.format(python_executable, os.path.join(root, 'harness.py')) harness = '{} {}'.format(python_executable, os.path.join(root, 'harness.py'))
config.substitutions.append( ('%python', harness) ) config.substitutions.append( ('%python', harness) )
not_ = '{} {}'.format(python_executable, os.path.join(root, 'not.py'))
config.substitutions.append( ('%not', not_) )
if os.name == 'posix': if os.name == 'posix':
personality_build = os.path.join(root, 'libartiq_personality') personality_build = os.path.join(root, 'libartiq_personality')
if subprocess.call(['make', '-sC', personality_build]) != 0: if subprocess.call(['make', '-sC', personality_build]) != 0:

View File

@ -1,25 +1,41 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <stdio.h> #include <stdio.h>
#include <unwind.h> #include <unwind.h>
#include "artiq_personality.h"
struct artiq_exception { #define ARTIQ_EXCEPTION_CLASS 0x4152545141525451LL // 'ARTQARTQ'
const char *name;
const char *file; struct artiq_raised_exception {
int32_t line; struct _Unwind_Exception unwind;
int32_t column; struct artiq_exception artiq;
const char *message;
int64_t param[3];
}; };
void __artiq_raise(struct artiq_exception *artiq_exn) { static void __artiq_cleanup(_Unwind_Reason_Code reason, struct _Unwind_Exception *exc) {
printf("raised %s\n", artiq_exn->name); struct artiq_raised_exception *inflight = (struct artiq_raised_exception*) exc;
abort(); // The in-flight exception is statically allocated, so we don't need to free it.
// But, we clear it to mark it as processed.
memset(&inflight->artiq, 0, sizeof(struct artiq_exception));
} }
_Unwind_Reason_Code __artiq_personality(int version, void __artiq_raise(struct artiq_exception *artiq_exn) {
_Unwind_Action actions, uint64_t exceptionClass, static struct artiq_raised_exception inflight;
struct _Unwind_Exception *exceptionObject, memcpy(&inflight.artiq, artiq_exn, sizeof(struct artiq_exception));
struct _Unwind_Context *context) { inflight.unwind.exception_class = ARTIQ_EXCEPTION_CLASS;
inflight.unwind.exception_cleanup = &__artiq_cleanup;
_Unwind_Reason_Code result = _Unwind_RaiseException(&inflight.unwind);
if(result == _URC_END_OF_STACK) {
__artiq_terminate(&inflight.artiq);
} else {
fprintf(stderr, "__artiq_raise: unexpected error (%d)\n", result);
abort();
}
}
_Unwind_Reason_Code __artiq_personality(
int version, _Unwind_Action actions, uint64_t exceptionClass,
struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context) {
abort(); abort();
} }

View File

@ -0,0 +1,31 @@
#ifndef __ARTIQ_PERSONALITY_H
#define __ARTIQ_PERSONALITY_H
#include <stdint.h>
struct artiq_exception {
union {
void *typeinfo;
const char *name;
};
const char *file;
int32_t line;
int32_t column;
const char *message;
int64_t param[3];
};
#ifdef __cplusplus
extern "C" {
#endif
void __artiq_terminate(struct artiq_exception *artiq_exn)
__attribute__((noreturn));
void __artiq_raise(struct artiq_exception *artiq_exn);
#ifdef __cplusplus
}
#endif
#endif /* __ARTIQ_PERSONALITY_H */