Terminating the whole checkasm process is not very helpful. This will report if an illegal instruction occurs while executing a tested function. This is a common occurrence whilst developping RISC-V assembler, due to the compatibility between vector configuration and instruction done at run-time.
Unified · Split
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | # define _GNU_SOURCE // for syscall (performance monitoring API), strsignal() |
| 28 | 28 | #endif |
| 29 | 29 | |
| 30 | +#include <signal.h> | |
| 30 | 31 | #include <stdarg.h> |
| 31 | 32 | #include <stdio.h> |
| 32 | 33 | #include <stdlib.h> |
| @@ -734,6 +735,14 @@ int main(int argc, char *argv[]) · 701 unmodified lines | ||
| 734 | 735 | if (have_vfp(av_get_cpu_flags()) || have_neon(av_get_cpu_flags())) |
| 735 | 736 | checkasm_checked_call = checkasm_checked_call_vfp; |
| 736 | 737 | #endif |
| 738 | +#if ARCH_RISCV | |
| 739 | + struct sigaction act = { | |
| 740 | + .sa_handler = checkasm_handle_signal, | |
| 741 | + .sa_flags = 0, | |
| 742 | + }; | |
| 743 | + | |
| 744 | + sigaction(SIGILL, &act, NULL); | |
| 745 | +#endif | |
| 737 | 746 | |
| 738 | 747 | if (!tests[0].func || !cpus[0].flag) { |
| 739 | 748 | fprintf(stderr, "checkasm: no tests to perform\n"); |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #ifndef TESTS_CHECKASM_CHECKASM_H |
| 24 | 24 | #define TESTS_CHECKASM_CHECKASM_H |
| 25 | 25 | |
| 26 | +#include <setjmp.h> | |
| 26 | 27 | #include <stdint.h> |
| 27 | 28 | #include "config.h" |
| 28 | 29 | |
| @@ -211,14 +212,20 @@ void checkasm_checked_call(void *func, ...); · 182 unmodified lines | ||
| 211 | 212 | checked_call(func_new, 0, 0, 0, 0, 0, 0, 0, __VA_ARGS__,\ |
| 212 | 213 | 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0)) |
| 213 | 214 | #elif ARCH_RISCV |
| 214 | −void checkasm_set_function(void *); | |
| 215 | +void checkasm_set_function(void *, sigjmp_buf); | |
| 215 | 216 | void *checkasm_get_wrapper(void); |
| 217 | +void checkasm_handle_signal(int signum); | |
| 216 | 218 | |
| 217 | 219 | #if (__riscv_xlen == 64) && defined (__riscv_d) |
| 218 | 220 | #define declare_new(ret, ...) \ |
| 221 | + int checked_call_signum = 0; \ | |
| 222 | + sigjmp_buf checked_call_jb; \ | |
| 219 | 223 | ret (*checked_call)(__VA_ARGS__) = checkasm_get_wrapper(); |
| 220 | 224 | #define call_new(...) \ |
| 221 | − (checkasm_set_function(func_new), checked_call(__VA_ARGS__)) | |
| 225 | + (checkasm_set_function(func_new, checked_call_jb), \ | |
| 226 | + (checked_call_signum = sigsetjmp(checked_call_jb, 1)) == 0 \ | |
| 227 | + ? checked_call(__VA_ARGS__) \ | |
| 228 | + : (checkasm_fail_signal(checked_call_signum), 0)) | |
| 222 | 229 | #endif |
| 223 | 230 | #else |
| 224 | 231 | #define declare_new(ret, ...) |
| @@ -41,6 +41,7 @@ endconst · 40 unmodified lines | ||
| 41 | 41 | |
| 42 | 42 | checked_func: |
| 43 | 43 | .quad 0 |
| 44 | + .quad 0 | |
| 44 | 45 | |
| 45 | 46 | saved_regs: |
| 46 | 47 | /* Space to spill RA, SP, GP, TP, S0-S11 and FS0-FS11 */ |
| @@ -52,6 +53,7 @@ func checkasm_set_function · 5 unmodified lines | ||
| 52 | 53 | la.tls.ie t0, checked_func |
| 53 | 54 | add t0, tp, t0 |
| 54 | 55 | sd a0, (t0) |
| 56 | + sd a1, 8(t0) | |
| 55 | 57 | ret |
| 56 | 58 | endfunc |
| 57 | 59 | |
| @@ -175,4 +177,14 @@ func checkasm_get_wrapper, v · 117 unmodified lines | ||
| 175 | 177 | call checkasm_fail_func |
| 176 | 178 | j 4b |
| 177 | 179 | endfunc |
| 180 | + | |
| 181 | +func checkasm_handle_signal | |
| 182 | + mv a1, a0 | |
| 183 | + la.tls.ie a0, checked_func | |
| 184 | + add a0, tp, a0 | |
| 185 | + ld a0, 8(a0) | |
| 186 | + beqz a0, 8f | |
| 187 | + tail siglongjmp | |
| 188 | +8: tail abort /* No jump buffer to go to */ | |
| 189 | +endfunc | |
| 178 | 190 | #endif |