split up CATCH_ERRORS into functional and semantic options

allows running a non-heapverify build that functions exactly as a heapverify one, while allowing ⎊ to function
This commit is contained in:
dzaima 2024-04-04 02:51:37 +03:00
parent fd317ddce3
commit 54cec2fdf5
14 changed files with 39 additions and 32 deletions

View File

@ -323,14 +323,14 @@ po ← { # parsed options
args (singeli arch"aarch64") / "-DSINGELI_NEON"
args (singeli arch<"x86-64""aarch64") / "-DSINGELI_SIMD"
args ( wasm) / "-DWASM"
args ( wasi) / "-DWASI", "-DNO_MMAP", "-DCATCH_ERRORS=0", "-D_WASI_EMULATED_MMAN", "--target=wasm32-wasi"
args ( wasi) / "-DWASI", "-DNO_MMAP", "-DUSE_SETJMP=0", "-D_WASI_EMULATED_MMAN", "--target=wasm32-wasi"
args ( emcc) / "-DEMCC", "-O3"
args ( replxx) / "-DUSE_REPLXX", "-DREPLXX_STATIC=1", "-I"replxxDir"/include" # TODO maybe move to main.c only, and have it be in its own separate cache dir, so that adding replxx doesn't recompile everything?
args ( debug DOpt "g") / "-g"
args ( o3) / "-O3"
args ( debug) / "-DDEBUG"
args ( rtverify) / "-DRT_VERIFY"
args ( heapverify) / "-DHEAP_VERIFY", "-DCATCH_ERRORS=0"
args ( heapverify) / "-DHEAP_VERIFY", "-DUSE_SETJMP=0"
args ( exportSymbols) / "-DCBQN_EXPORT"
args ( ¬pie) / "-fno-pie"
args (pie ¬sharedLib) / "-fPIE"

View File

@ -401,7 +401,7 @@ Most toggles require a value of `1` to be enabled.
```c
// (effective) usual default value is listed; (u) marks being not defined
// default may change under some conditions (DEBUG, CATCH_ERRORS, heapverify, among maybe other things)
// defaults may change under some conditions (DEBUG, USE_SETJMP, heapverify, among maybe other things)
// some things fully configured by the build system may not be listed
// general config:
@ -420,7 +420,6 @@ Most toggles require a value of `1` to be enabled.
#define ALL_R0 0 // use all of r0.bqn for runtime_0
#define ALL_R1 0 // use all of r1.bqn for runtime
#define NO_RT 0 // whether to completely disable self-hosted runtime loading
#define CATCH_ERRORS 1 // allow catching errors; means refcounts might stay too high if forgotten over a throw-catch; disabled for heapverify
#define FAKE_RUNTIME 0 // disable the self-hosted runtime
#define FORMATTER 1 // use self-hosted formatter for output
#define NO_EXPLAIN 0 // disable )explain
@ -429,6 +428,9 @@ Most toggles require a value of `1` to be enabled.
#define SFNS_FILLS 1 // compute fills for structural functions (∾, ≍, etc)
#define CHECK_VALID 1 // check for valid arguments in places where that would be detrimental to performance
// e.g. left argument sortedness of ⍋/⍒, incompatible changes in ⌾, etc
#define USE_SETJMP 1 // whether setjmp is available & should be used for error catching (makes refcounts leakable)
#define SEMANTIC_CATCH USE_SETJMP // whether catching should be assumed to be usable for operations which need to semantically change depending on that
#define SEMANTIC_CATCH_BI SEMANTIC_CATCH // whether ⎊ will catch stuff
#define RYU_OPTIMIZE_SIZE 0 // reduce size of Ryu tables at the cost of some performance for number •Repr
#define FFI_CHECKS 1 // check for valid arguments passed to FFI-d functions

View File

@ -83,12 +83,12 @@ B scan_arith(B f, B w, B x, usz* xsh) { // Used by scan.c
#if TEST_CELL_FILLS
i32 fullCellFills = 2*CATCH_ERRORS;
i32 fullCellFills = 2*SEMANTIC_CATCH;
i32 cellFillErrored = 0;
#define DO_CELL_CATCH (fullCellFills==2)
#define SET_FILL_ERRORED cellFillErrored = 1
#else
#define DO_CELL_CATCH CATCH_ERRORS
#define DO_CELL_CATCH SEMANTIC_CATCH
#define SET_FILL_ERRORED
#endif

View File

@ -8,9 +8,7 @@
B val_c1(Md2D* d, B x) { return c1(d->f, x); }
B val_c2(Md2D* d, B w, B x) { return c2(d->g, w,x); }
#if CATCH_ERRORS && !BI_CATCH_DISABLED
extern GLOBAL B lastErrMsg; // sysfn.c
#if SEMANTIC_CATCH
B fillBy_c1(Md2D* d, B x) {
B xf=getFillQ(x);
B r = c1(d->f, x);
@ -30,7 +28,13 @@ B fillBy_c2(Md2D* d, B w, B x) {
popCatch();
return withFill(r, fill);
}
#else
B fillBy_c1(Md2D* d, B x) { return c1(d->f, x); }
B fillBy_c2(Md2D* d, B w, B x) { return c2(d->f, w,x); }
#endif
#if defined(SEMANTIC_CATCH_BI)? SEMANTIC_CATCH_BI : SEMANTIC_CATCH
extern GLOBAL B lastErrMsg; // sysfn.c
typedef struct ReObj {
struct CustomObj;
B msg;
@ -48,8 +52,6 @@ void pushRe(void) {
B catch_c1(Md2D* d, B x) { if(CATCH) { pushRe(); B r = c1(d->g, x); dec(gsPop()); return r; } B r = c1(d->f, inc(x)); popCatch(); dec(x); return r; }
B catch_c2(Md2D* d, B w, B x) { if(CATCH) { pushRe(); B r = c2(d->g, w,x); dec(gsPop()); return r; } B r = c2(d->f, inc(w),inc(x)); popCatch(); dec(w); dec(x); return r; }
#else
B fillBy_c1(Md2D* d, B x) { return c1(d->f, x); }
B fillBy_c2(Md2D* d, B w, B x) { return c2(d->f, w,x); }
B catch_c1(Md2D* d, B x) { return c1(d->f, x); }
B catch_c2(Md2D* d, B w, B x) { return c2(d->f, w,x); }
#endif

View File

@ -701,7 +701,7 @@ B repl_c1(B t, B x) {
return repl_c2(t, emptyHVec(), x);
}
#if CATCH_ERRORS
#if USE_SETJMP
GLOBAL B lastErrMsg;
B currentError_c1(B t, B x) {
if (isNsp(x)) thrM("•CurrentError: Namespace 𝕩 is reserved");
@ -1992,7 +1992,7 @@ void sysfn_init(void) {
#undef F
NOGC_E;
#if CATCH_ERRORS
#if USE_SETJMP
lastErrMsg = bi_N;
gc_add_ref(&lastErrMsg);
#endif

View File

@ -59,9 +59,9 @@ static B getFillR(B x) { // doesn't consume; can return bi_noFill
if (isC32(x)) return m_c32(' ');
return bi_noFill;
}
static B getFillQ(B x) { // doesn't consume; returns 0 if !CATCH_ERRORS
static B getFillQ(B x) { // doesn't consume; returns 0 if !SEMANTIC_CATCH
B r = getFillR(x);
#if CATCH_ERRORS
#if SEMANTIC_CATCH
return r;
#endif
return noFill(r)? m_f64(0) : r;

15
src/h.h
View File

@ -1,7 +1,7 @@
#pragma once
#ifndef CATCH_ERRORS
#define CATCH_ERRORS 1
#ifndef USE_SETJMP
#define USE_SETJMP 1
#endif
#ifndef ENABLE_GC
#define ENABLE_GC 1
@ -43,14 +43,17 @@
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#if CATCH_ERRORS
#if USE_SETJMP
#include <setjmp.h>
#endif
#define RT_LEN 64
#if CATCH_ERRORS
#define PROPER_FILLS (EACH_FILLS&SFNS_FILLS)
#ifndef SEMANTIC_CATCH
#define SEMANTIC_CATCH USE_SETJMP
#endif
#if SEMANTIC_CATCH
#define PROPER_FILLS (EACH_FILLS & SFNS_FILLS)
#else
#undef EACH_FILLS
#define EACH_FILLS 0
@ -393,7 +396,7 @@ NOINLINE NORETURN void rethrow(void);
NOINLINE NORETURN void thrM(char* s);
NOINLINE NORETURN void thrF(char* s, ...);
NOINLINE NORETURN void thrOOM(void);
#if CATCH_ERRORS
#if USE_SETJMP
jmp_buf* prepareCatch(void);
#define CATCH setjmp(*prepareCatch()) // use as `if (CATCH) { /*handle error*/ freeThrown(); return; } /*potentially erroring thing*/ popCatch(); /*no errors yay*/`
void popCatch(void); // note: popCatch() must always be called if no error is thrown, so no returns before it!

View File

@ -659,7 +659,7 @@ B bqn_explain(B str) {
static void freed_visit(Value* x) {
#if CATCH_ERRORS
#if USE_SETJMP
fatal("visiting t_freed\n");
#endif
}

View File

@ -54,7 +54,7 @@ void gc_visitRoots() {
static void gc_tryFree(Value* v) {
u8 t = v->type;
#if DEBUG && !CATCH_ERRORS
#if DEBUG && !USE_SETJMP
if (t==t_freed) fatal("GC found t_freed\n");
#endif
if (t!=t_empty && !(v->mmInfo&0x80)) {
@ -62,7 +62,7 @@ static void gc_tryFree(Value* v) {
#if DONT_FREE
v->flags = t;
#else
#if CATCH_ERRORS
#if USE_SETJMP
if (t==t_freed) { mm_free(v); return; }
#endif
#endif

View File

@ -121,7 +121,7 @@ B eachm_fn(B fo, B x, FC1 f) {
return any_squeeze(HARR_FCD(r, x));
}
#if CATCH_ERRORS
#if SEMANTIC_CATCH
B arith_recd(FC2 f, B w, B x) {
B fx = getFillR(x);
if (noFill(fx)) return eachd_fn(bi_N, w, x, f);

View File

@ -4,7 +4,7 @@ B eachd_fn(B fo, B w, B x, FC2 f); // consumes w,x; assumes at least one is arra
B eachm_fn(B fo, B x, FC1 f); // consumes x; x must be array
#if CATCH_ERRORS
#if SEMANTIC_CATCH
NOINLINE B arith_recd(FC2 f, B w, B x);
#else
static inline B arith_recd(FC2 f, B w, B x) { return eachd_fn(bi_N, w, x, f); }

View File

@ -128,7 +128,7 @@ void fprintsB(FILE* f, B x) {
for (usz i = 0; i < ia; i++) {
B c = GetU(x, i);
if (isC32(c)) fprintCodepoint(f, o2cG(c));
#if !CATCH_ERRORS
#if !SEMANTIC_CATCH
else if (c.u==0 || noFill(c)) fprintf(f, " ");
#endif
else thrM("Trying to output non-character");

View File

@ -1299,7 +1299,7 @@ void comp_init(void) {
typedef struct CatchFrame {
#if CATCH_ERRORS
#if USE_SETJMP
jmp_buf jmp;
#endif
u64 gsDepth;
@ -1310,7 +1310,7 @@ GLOBAL CatchFrame* cf; // points to after end
GLOBAL CatchFrame* cfStart;
GLOBAL CatchFrame* cfEnd;
#if CATCH_ERRORS
#if USE_SETJMP
jmp_buf* prepareCatch() {
if (cf==cfEnd) {
u64 n = cfEnd-cfStart;
@ -1689,7 +1689,7 @@ NOINLINE NORETURN void throwImpl(bool rethrow) {
// while (c>gStackStart) { printI(*--c); putchar('\n'); } printf("gStack printed\n");
NOGC_CHECK("throwing during noAlloc");
if (!rethrow) envPrevHeight = envCurr-envStart + 1;
#if CATCH_ERRORS
#if USE_SETJMP
if (cf>cfStart) { // something wants to catch errors
cf--;
@ -1715,7 +1715,7 @@ NOINLINE NORETURN void throwImpl(bool rethrow) {
#else
exit(1);
#endif
#if CATCH_ERRORS
#if USE_SETJMP
}
#endif
}

View File

@ -3,7 +3,7 @@ if [ "$#" -ne 1 ]; then
echo "Usage: $0 path/to/mlochbaum/BQN"
exit
fi
make f='-DDEBUG -DHEAP_VERIFY -DJIT_START=0' single-c
make f='-DDEBUG -DHEAP_VERIFY -DUSE_SETJMP=0 -DJIT_START=0' single-c
echo 'alljit+heapverify:' && ./BQN -M 1000 "$1/test/this.bqn" -noerr bytecode header identity literal namespace prim simple syntax token under undo unhead || exit
echo 'native vfy:';make heapverifyn && ./BQN -M 1000 "$1/test/this.bqn" -noerr bytecode header identity literal namespace prim simple syntax token under undo unhead || exit
echo 'native:';make o3n && ./BQN -M 1000 "$1/test/this.bqn" || exit