diff options
Diffstat (limited to 'core/module-run.h')
| -rw-r--r-- | core/module-run.h | 72 |
1 files changed, 67 insertions, 5 deletions
diff --git a/core/module-run.h b/core/module-run.h index fac77a4..1e48072 100644 --- a/core/module-run.h +++ b/core/module-run.h @@ -4,9 +4,59 @@ * (module-jit.c): their frame, and the steps the compiled code calls. Not a * public interface. */ #include "module.h" +#include <math.h> +#include <string.h> -/* An item's or a key's op->plan: its cell a text; a FIND joined to the ITEM_GET after it. */ -enum { PLAN_TEXT = 1, PLAN_JOINED = 2, PLAN_ROW = 4 }; +/* Read from a message's bytes (little-endian). */ +static inline uint32_t read32(const unsigned char *p) { + return (uint32_t)p[0] | (uint32_t)p[1] << 8 | (uint32_t)p[2] << 16 | (uint32_t)p[3] << 24; +} + +static inline double read_double(const unsigned char *p) { + uint64_t bits = read32(p) | (uint64_t)read32(p + 4) << 32; + double value; + memcpy(&value, &bits, sizeof(value)); + return value; +} + +static inline double minimum(double a, double b) { return a < b || (a == b && signbit(a)) ? a : b; } +static inline double maximum(double a, double b) { return a > b || (a == b && !signbit(a)) ? a : b; } + +/* a op b as run computes it; false where run faults. */ +static inline bool number_op(uint8_t op, double a, double b, double *out) { + double value; + switch (op) { + case PURE_OP_ADD: value = a + b; break; + case PURE_OP_SUB: value = a - b; break; + case PURE_OP_MUL: value = a * b; break; + case PURE_OP_DIV: + if (b == 0) return false; + value = a / b; + break; + case PURE_OP_LT: value = a < b; break; + case PURE_OP_LE: value = a <= b; break; + case PURE_OP_GT: value = a > b; break; + case PURE_OP_GE: value = a >= b; break; + case PURE_OP_EQ: value = a == b; break; + case PURE_OP_NE: value = a != b; break; + case PURE_OP_AND: value = a != 0 && b != 0; break; + case PURE_OP_OR: value = a != 0 || b != 0; break; + case PURE_OP_MIN: value = minimum(a, b); break; + case PURE_OP_MOD: + if (b == 0) return false; + value = fmod(a, b); + if (value != 0 && (value < 0) != (b < 0)) value += b; + else if (value == 0) value = copysign(0.0, b); + break; + default: value = maximum(a, b); break; + } + *out = value; + return isfinite(value); +} + +/* An item's or a key's op->plan: its cell a text; a FIND joined to the ITEM_GET after it; a FIND whose row an ITEM_SET + * takes; a LOOP whose block a batch may run (module-batch.c). */ +enum { PLAN_TEXT = 1, PLAN_JOINED = 2, PLAN_ROW = 4, PLAN_BATCH = 8 }; /* An item instruction's argument: its list and its field. */ static inline uint32_t list_of(uint32_t arg) { return arg & 0xFFFF; } @@ -20,7 +70,8 @@ typedef struct { uint32_t list; size_t at, end; bool removed; } Walk; /* A loop that runs in its block's run (LOOP, EACH): its block and where * the code around it ends, the arena as it began, a walk's walk and the * event's walk and row around it, a count's values (low + k of count) and - * slot. */ + * slot, and the round from which batches may run its rounds (UINT64_MAX: + * none), how many failed and which way their lanes run. */ typedef struct { uint32_t start, end, outer; size_t mark; @@ -29,6 +80,9 @@ typedef struct { size_t row; uint64_t count, k; PureValue low, *slot; + uint64_t resume; + unsigned failures; + bool reverse; /* a batch's lanes run its rounds backwards */ } Loop; typedef struct { PureApp *app; @@ -83,8 +137,9 @@ static inline uint32_t after(const PureOp *op, uint32_t pc) { * instruction but a branch or a loop's (how; the next is after()); a walk or * a loop opened at pc (STEP_NEXT: its block next, STEP_SKIP: none, past its * block); BREAK; a loop's block ran once (STEP_NEXT: again, STEP_DONE: the - * loop ended). */ -enum { STEP_SKIP = 4, STEP_DONE = 5 }; + * loop ended). STEP_BATCH: step leaves a LOOP planned PLAN_BATCH to its + * caller (module.c). */ +enum { STEP_SKIP = 4, STEP_DONE = 5, STEP_BATCH = 6 }; int pure_run_step(Frame *, uint32_t pc); int pure_run_each(Frame *, uint32_t pc); int pure_run_loop(Frame *, uint32_t pc); @@ -101,6 +156,13 @@ int pure_run_item(Frame *, uint32_t pc); * stopped. */ int pure_run_rest(Frame *, uint32_t pc); +/* Loops a batch of rounds at a time (module-batch.c, docs/design/024): the + * innermost loop's rounds from loop->k (set up and counted; its LOOP + * planned PLAN_BATCH) run as one batch: how many (0: none ran, its block + * runs round by round next, at least until round loop->resume), the frame + * left as the last of them leaves it, their work counted. */ +unsigned pure_batch_run(Frame *, Loop *); + /* Where a list keeps what compiled code reads of it (module-list.c owns the * layout and says where): its item count, its key set (the words, how many, * whether they are bits), its form (pure_list_form), its arrays and the rows |
