2#define REDUCT_OPCODE_H 1
171typedef struct reduct_opcode_info
188#define REDUCT_OPCODE_BASE(_op) ((_op) & ~REDUCT_OPCODE_MODE_CONST)
195#define REDUCT_OPCODE_GET_NAME(_op) (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].name)
202#define REDUCT_OPCODE_GET_LAYOUT(_op) (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].layout)
209#define REDUCT_OPCODE_IS_COMPARE(_op) \
210 (REDUCT_OPCODE_BASE(_op) >= REDUCT_OPCODE_EQ && REDUCT_OPCODE_BASE(_op) <= REDUCT_OPCODE_GE)
217#define REDUCT_OPCODE_TO_SKIP(_op) \
218 (REDUCT_OPCODE_IS_COMPARE(_op) ? (reduct_opcode_t)((_op) + (REDUCT_OPCODE_JEQ - REDUCT_OPCODE_EQ)) \
226#define REDUCT_OPCODE_INVERT_SKIP(_op) \
227 ((reduct_opcode_t)((REDUCT_OPCODE_BASE(_op) == REDUCT_OPCODE_JEQ ? REDUCT_OPCODE_JNEQ \
228 : REDUCT_OPCODE_BASE(_op) == REDUCT_OPCODE_JNEQ ? REDUCT_OPCODE_JEQ \
229 : REDUCT_OPCODE_BASE(_op) == REDUCT_OPCODE_JLT ? REDUCT_OPCODE_JGE \
230 : REDUCT_OPCODE_BASE(_op) == REDUCT_OPCODE_JGE ? REDUCT_OPCODE_JLT \
231 : REDUCT_OPCODE_BASE(_op) == REDUCT_OPCODE_JLE ? REDUCT_OPCODE_JGT \
232 : REDUCT_OPCODE_BASE(_op) == REDUCT_OPCODE_JGT ? REDUCT_OPCODE_JLE \
234 ((_op) & REDUCT_OPCODE_MODE_CONST)))
241#define REDUCT_OPCODE_TO_RECUR(_op) \
242 (REDUCT_OPCODE_IS_CALL(_op) \
243 ? (reduct_opcode_t)((REDUCT_OPCODE_BASE(_op) == REDUCT_OPCODE_TAILCALL) ? REDUCT_OPCODE_TAILRECUR \
244 : REDUCT_OPCODE_RECUR) \
252#define REDUCT_OPCODE_TO_TAIL(_op) \
253 ((_op) == REDUCT_OPCODE_CALL ? REDUCT_OPCODE_TAILCALL \
254 : (_op) == REDUCT_OPCODE_CALL_CONST ? REDUCT_OPCODE_TAILCALL_CONST \
255 : (_op) == REDUCT_OPCODE_RECUR ? REDUCT_OPCODE_TAILRECUR \
263#define REDUCT_OPCODE_HAS_TARGET(_op) (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_HAS_TARGET)
270#define REDUCT_OPCODE_IS_RECUR(_op) (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_IS_RECUR)
277#define REDUCT_OPCODE_IS_JUMP(_op) (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_IS_JUMP)
284#define REDUCT_OPCODE_HAS_CONST(_op) (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_HAS_CONST)
291#define REDUCT_OPCODE_READS_A(_op) (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_READ_A)
298#define REDUCT_OPCODE_READS_B(_op) (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_READ_B)
305#define REDUCT_OPCODE_READS_C(_op) (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_READ_C)
312#define REDUCT_OPCODE_READS_RANGE(_op) \
313 (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_READ_RANGE)
320#define REDUCT_OPCODE_IS_COMMUTATIVE(_op) \
321 (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_IS_COMMUTATIVE)
328#define REDUCT_OPCODE_IS_SKIP(_op) (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_IS_SKIP)
335#define REDUCT_OPCODE_IS_BRANCH(_op) \
336 (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & (REDUCT_OPCODE_FLAG_IS_SKIP | REDUCT_OPCODE_FLAG_IS_JUMP))
343#define REDUCT_OPCODE_IS_CALL(_op) (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_IS_CALL)
350#define REDUCT_OPCODE_IS_TERMINATOR(_op) \
351 (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_IS_TERMINATOR)
358#define REDUCT_OPCODE_IS_BINARY(_op) \
359 ((reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & (REDUCT_OPCODE_FLAG_READ_B | REDUCT_OPCODE_FLAG_READ_C)) == \
360 (REDUCT_OPCODE_FLAG_READ_B | REDUCT_OPCODE_FLAG_READ_C))
367#define REDUCT_OPCODE_IS_TERNARY(_op) \
368 ((reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & \
369 (REDUCT_OPCODE_FLAG_READ_A | REDUCT_OPCODE_FLAG_READ_B | REDUCT_OPCODE_FLAG_READ_C)) == \
370 (REDUCT_OPCODE_FLAG_READ_A | REDUCT_OPCODE_FLAG_READ_B | REDUCT_OPCODE_FLAG_READ_C))
377#define REDUCT_OPCODE_IS_UNARY(_op) \
378 ((reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & \
379 (REDUCT_OPCODE_FLAG_READ_A | REDUCT_OPCODE_FLAG_READ_B | REDUCT_OPCODE_FLAG_READ_C)) == \
380 REDUCT_OPCODE_FLAG_READ_C)
387#define REDUCT_OPCODE_IS_FORK(_op) (reductOpcodeTable[REDUCT_OPCODE_BASE(_op)].flags & REDUCT_OPCODE_FLAG_IS_FORK)
reduct_opcode_layout_t
Opcode operand layouts.
reduct_opcode_flags_t
Opcode flags.
reduct_opcode_t
Opcode enumeration.
REDUCT_API const reduct_opcode_info_t reductOpcodeTable[128]
Opcode information and flags table.
reduct_opcode_mode_t
Opcode mode enumeration.
@ REDUCT_LAYOUT_NONE
No operands.
@ REDUCT_LAYOUT_ABC
R(A) R(B) R/K(C)
@ REDUCT_LAYOUT_ABC_RANGE
R(A) B R/K(C)
@ REDUCT_LAYOUT_AC
R(A) R/K(C)
@ REDUCT_LAYOUT_AB
R(A) R(B)
@ REDUCT_LAYOUT_SAXC
sAx R/K(C)
@ REDUCT_LAYOUT_AB_RANGE
R(A) B.
@ REDUCT_OPCODE_FLAG_IS_SKIP
Opcode is a skip instruction.
@ REDUCT_OPCODE_FLAG_IS_COMMUTATIVE
Opcode is commutative.
@ REDUCT_OPCODE_FLAG_READ_RANGE
Opcode reads a range of registers starting at A.
@ REDUCT_OPCODE_FLAG_HAS_TARGET
Opcode modifies target register A.
@ REDUCT_OPCODE_FLAG_IS_FORK
Opcode returns a task handle.
@ REDUCT_OPCODE_FLAG_READ_C
Opcode reads from register/constant C.
@ REDUCT_OPCODE_FLAG_IS_CALL
Opcode is a function call.
@ REDUCT_OPCODE_FLAG_IS_JUMP
Opcode is a jump.
@ REDUCT_OPCODE_FLAG_IS_TERMINATOR
Opcode ends basic block reachability.
@ REDUCT_OPCODE_FLAG_HAS_CONST
Opcode uses C operand and has both reg/const versions.
@ REDUCT_OPCODE_FLAG_READ_B
Opcode reads from register B.
@ REDUCT_OPCODE_FLAG_IS_RECUR
Opcode is a recursive call.
@ REDUCT_OPCODE_FLAG_READ_A
Opcode reads from register A (or range starting at A).
@ REDUCT_OPCODE_NTH3
(A, B, C) R(A) = R(A)[R(B)][R/K(C)]
@ REDUCT_OPCODE_LAST
(A, C) R(A) = last(R/K(C))
@ REDUCT_OPCODE_JGE_CONST
@ REDUCT_OPCODE_SUB_CONST
@ REDUCT_OPCODE_DIV
(A, B, C) R(A) = R(B) / R/K(C)
@ REDUCT_OPCODE_JLT_CONST
@ REDUCT_OPCODE_JMPF
(sAx, C) Jump by sAx if R(C) is falsy.
@ REDUCT_OPCODE_JMPT
(sAx, C) Jump by sAx if R(C) is truthy.
@ REDUCT_OPCODE_RECUR
(A, B) Recursively call the current function with B args starting from R(A).
@ REDUCT_OPCODE_DIV_CONST
@ REDUCT_OPCODE_MOD_CONST
@ REDUCT_OPCODE_RANGE2_CONST
@ REDUCT_OPCODE_APPEND
(A, B) R(A) = append(R(A), R(A + 1) ... R(A + B - 1))
@ REDUCT_OPCODE_SHR
(A, B, C) R(A) = R(B) >> R/K(C)
@ REDUCT_OPCODE_BXOR_CONST
@ REDUCT_OPCODE_BNOT_CONST
@ REDUCT_OPCODE_JEQ_CONST
@ REDUCT_OPCODE_SHL_CONST
@ REDUCT_OPCODE_SHL
(A, B, C) R(A) = R(B) << R/K(C)
@ REDUCT_OPCODE_SUB
(A, B, C) R(A) = R(B) - R/K(C)
@ REDUCT_OPCODE_INIT_CONST
@ REDUCT_OPCODE_RANGE2
(A, B, C) R(A) = range(R(B), R/K(C), 1)
@ REDUCT_OPCODE_NEQ
(A, B, C) If R(B) != R/K(C) store true in R(A), else false.
@ REDUCT_OPCODE_JNEQ_CONST
@ REDUCT_OPCODE_NTH3_CONST
@ REDUCT_OPCODE_CONCAT
(A, B) R(A) = concat(R(A) ... R(A + B - 1))
@ REDUCT_OPCODE_BOR_CONST
@ REDUCT_OPCODE_MOV
(A, C) Move value in R/K(C) to R(A).
@ REDUCT_OPCODE_INIT
(A, C) R(A) = init(R/K(C))
@ REDUCT_OPCODE_JLE_CONST
@ REDUCT_OPCODE_JGT
(B, C) Skip the next instruction if R(B) > R/K(C), else continue.
@ REDUCT_OPCODE_MUL
(A, B, C) R(A) = R(B) * R/K(C)
@ REDUCT_OPCODE_JNEQ
(B, C) Skip the next instruction if R(B) != R/K(C), else continue.
@ REDUCT_OPCODE_FIRST_CONST
@ REDUCT_OPCODE_ADD
(A, B, C) R(A) = R(B) + R/K(C)
@ REDUCT_OPCODE_JLE
(B, C) Skip the next instruction if R(B) <= R/K(C), else continue.
@ REDUCT_OPCODE_BAND
(A, B, C) R(A) = R(B) & R/K(C)
@ REDUCT_OPCODE_ADD_CONST
@ REDUCT_OPCODE_RET
(C) Return value in R/K(C).
@ REDUCT_OPCODE_CAPTURE_CONST
@ REDUCT_OPCODE_BNOT
(A, C) R(A) = ~R/K(C)
@ REDUCT_OPCODE_LEN_CONST
@ REDUCT_OPCODE_BAND_CONST
@ REDUCT_OPCODE_EQ
(A, B, C) If R(B) == R/K(C) store true in R(A), else false.
@ REDUCT_OPCODE_RANGE3_CONST
@ REDUCT_OPCODE_SHR_CONST
@ REDUCT_OPCODE_LEN
(A, C) R(A) = length of R/K(C)
@ REDUCT_OPCODE_JOIN
(A, C) Wait for task handle in R(C) to complete, result stored in R(A).
@ REDUCT_OPCODE_CALL
(A, B, C) Call callable in R/K(C) with B args starting from R(A). Result in R(A).
@ REDUCT_OPCODE_GT
(A, B, C) If R(B) > R/K(C) store true in R(A), else false.
@ REDUCT_OPCODE_JMP
(sAx) Unconditional jump by relative offset sAx.
@ REDUCT_OPCODE_FORK_CONST
@ REDUCT_OPCODE_PREPEND
(A, B) R(A) = prepend(R(A), R(A + 1) ... R(A + B - 1))
@ REDUCT_OPCODE_NOP
No operation.
@ REDUCT_OPCODE_MOV_CONST
@ REDUCT_OPCODE_GE
(A, B, C) If R(B) >= R/K(C) store true in R(A), else false.
@ REDUCT_OPCODE_JGE
(B, C) Skip the next instruction if R(B) >= R/K(C), else continue.
@ REDUCT_OPCODE_BOR
(A, B, C) R(A) = R(B) | R/K(C)
@ REDUCT_OPCODE_LAST_CONST
@ REDUCT_OPCODE_CLOSURE
(A, C) Wrap the function prototype in K(C) in a closure and store in R(A).
@ REDUCT_OPCODE_JEQ
(B, C) Skip the next instruction if R(B) == R/K(C), else continue.
@ REDUCT_OPCODE_CALL_CONST
@ REDUCT_OPCODE_RANGE1
(A, C) R(A) = range(0, R/K(C), 1)
@ REDUCT_OPCODE_LE
(A, B, C) If R(B) <= R/K(C) store true in R(A), else false.
@ REDUCT_OPCODE_TAILCALL_CONST
@ REDUCT_OPCODE_LIST
(A, B) R(A) = (R(A) R(A + 1) ... R(A + B - 1))
@ REDUCT_OPCODE_JOIN_CONST
@ REDUCT_OPCODE_NTH2_CONST
@ REDUCT_OPCODE_REST
(A, C) R(A) = rest(R/K(C))
@ REDUCT_OPCODE_RANGE3
(A, B, C) R(A) = range(R(A), R(B), R/K(C))
@ REDUCT_OPCODE_TAILCALL
(A, B, C) Tail call callable in R/K(C) with B args starting from R(A).
@ REDUCT_OPCODE_TAILRECUR
(A, B) Recursively tail call the current function with B args starting from R(A).
@ REDUCT_OPCODE_BXOR
(A, B, C) R(A) = R(B) ^ R/K(C)
@ REDUCT_OPCODE_CAPTURE
(A, B, C) Capture R/K(C) into constant slot B in closure R(A).
@ REDUCT_OPCODE_REST_CONST
@ REDUCT_OPCODE_JLT
(B, C) Skip the next instruction if R(B) < R/K(C), else continue.
@ REDUCT_OPCODE_RANGE1_CONST
@ REDUCT_OPCODE_MOD
(A, B, C) R(A) = R(B) % R/K(C)
@ REDUCT_OPCODE_REPEAT
(A, B, C) R(A) = repeat(R(B), R/K(C))
@ REDUCT_OPCODE_JGT_CONST
@ REDUCT_OPCODE_FIRST
(A, C) R(A) = first(R/K(C))
@ REDUCT_OPCODE_LT
(A, B, C) If R(B) < R/K(C) store true in R(A), else false.
@ REDUCT_OPCODE_NTH2
(A, B, C) R(A) = R(B)[R/K(C)]
@ REDUCT_OPCODE_MUL_CONST
@ REDUCT_OPCODE_REPEAT_CONST
@ REDUCT_OPCODE_RET_CONST
@ REDUCT_OPCODE_NEQ_CONST
@ REDUCT_OPCODE_MODE_REG
Register operand mode.
@ REDUCT_OPCODE_MODE_CONST
Constant operand mode.
Opcode information structure.
reduct_opcode_flags_t flags
reduct_opcode_layout_t layout