aboutsummaryrefslogtreecommitdiff
path: root/src/fasm/runner
diff options
context:
space:
mode:
Diffstat (limited to 'src/fasm/runner')
-rw-r--r--src/fasm/runner/runner.c646
-rw-r--r--src/fasm/runner/runner.h36
2 files changed, 682 insertions, 0 deletions
diff --git a/src/fasm/runner/runner.c b/src/fasm/runner/runner.c
new file mode 100644
index 0000000..c01db18
--- /dev/null
+++ b/src/fasm/runner/runner.c
@@ -0,0 +1,646 @@
+#include "runner.h"
+
+#include <fasm/lexer/lexer.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syscall.h>
+#include <unistd.h>
+#include <utils/memory/memory.h>
+
+#define PUSHN(bits) \
+ pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, \
+ getNext##bits##Bits(&ip)); \
+ ip += bits / 8
+
+#define LOADN(bits) \
+ pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, \
+ *((uint##bits##_t *)popFromStack64Bits( \
+ &stack, &stack_size, &stack_filled)))
+
+#define POPN(bits) \
+ { \
+ uint##bits##_t *pointer = (uint##bits##_t *)popFromStack64Bits( \
+ &stack, &stack_size, &stack_filled); \
+ *pointer = popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \
+ }
+
+#define DUPN(bits) \
+ { \
+ const uint##bits##_t a = \
+ popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \
+ pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, a); \
+ pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, a); \
+ }
+
+#define SWAPN(bits) \
+ { \
+ const uint##bits##_t a = \
+ popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \
+ const uint##bits##_t b = \
+ popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \
+ pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, a); \
+ pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, b); \
+ }
+
+#define DROPN(bits) \
+ popFromStack##bits##Bits(&stack, &stack_size, &stack_filled);
+
+#define OPERATION(type, bits, op) \
+ { \
+ const type a = \
+ popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \
+ const type b = \
+ popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \
+ const type result = a op b; \
+ pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, \
+ *(uint##bits##_t *)&result); \
+ }
+
+#define ADD(type, bits) OPERATION(type, bits, +)
+
+#define SUB(type, bits) OPERATION(type, bits, -)
+
+#define NEG(type, bits) \
+ { \
+ const type a = \
+ popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \
+ const type result = -a; \
+ pushToStack##bits##Bits(&stack, &stack_size, &stack_filled, \
+ *(uint##bits##_t *)&result); \
+ }
+
+#define MUL(type, bits) OPERATION(type, bits, *)
+
+#define DIV(type, bits) OPERATION(type, bits, /)
+
+#define REM(type, bits) OPERATION(type, bits, %)
+
+#define CAST(from, from_bits, to, to_bits) \
+ { \
+ const from a = \
+ popFromStack##from_bits##Bits(&stack, &stack_size, &stack_filled); \
+ const to result = a; \
+ pushToStack##to_bits##Bits(&stack, &stack_size, &stack_filled, \
+ *(uint##to_bits##_t *)&result); \
+ }
+
+#define COND_JUMP(type, bits, op) \
+ { \
+ const uint##bits##_t a = \
+ popFromStack##bits##Bits(&stack, &stack_size, &stack_filled); \
+ \
+ if (*((type *)&a)op 0) { \
+ ip = (uint8_t *)popFromStack64Bits(&stack, &stack_size, &stack_filled); \
+ } \
+ }
+
+int fasmRunner(ByteCode bytecode) {
+ uint8_t *data = a404m_malloc(bytecode.data_size);
+ size_t data_size = bytecode.data_size;
+ memcpy(data, bytecode.data, data_size);
+
+ size_t stack_size = 0;
+ size_t stack_filled = 0;
+ uint8_t *stack = a404m_malloc(stack_size);
+
+ size_t functions_size = 0;
+ size_t functions_index = -1;
+ FasmFunction *functions = a404m_malloc(functions_size * sizeof(*functions));
+
+ uint8_t *ip = bytecode.code;
+
+ while (true) {
+ const FasmToken instruction = *ip;
+ ++ip;
+ switch (instruction) {
+ case FASM_TOKEN_NOOP:
+ break;
+ case FASM_TOKEN_PUSH8:
+ PUSHN(8);
+ break;
+ case FASM_TOKEN_PUSH16:
+ PUSHN(16);
+ break;
+ case FASM_TOKEN_PUSH32:
+ PUSHN(32);
+ break;
+ case FASM_TOKEN_PUSH64:
+ PUSHN(64);
+ break;
+ case FASM_TOKEN_LOAD8:
+ LOADN(8);
+ break;
+ case FASM_TOKEN_LOAD16:
+ LOADN(16);
+ break;
+ case FASM_TOKEN_LOAD32:
+ LOADN(32);
+ break;
+ case FASM_TOKEN_LOAD64:
+ LOADN(64);
+ break;
+ case FASM_TOKEN_POP8:
+ POPN(8);
+ break;
+ case FASM_TOKEN_POP16:
+ POPN(16);
+ break;
+ case FASM_TOKEN_POP32:
+ POPN(32);
+ break;
+ case FASM_TOKEN_POP64:
+ POPN(64);
+ break;
+ case FASM_TOKEN_DUP8:
+ DUPN(8);
+ break;
+ case FASM_TOKEN_DUP16:
+ DUPN(16);
+ break;
+ case FASM_TOKEN_DUP32:
+ DUPN(32);
+ break;
+ case FASM_TOKEN_DUP64:
+ DUPN(64);
+ break;
+ case FASM_TOKEN_SWAP8:
+ SWAPN(8);
+ break;
+ case FASM_TOKEN_SWAP16:
+ SWAPN(16);
+ break;
+ case FASM_TOKEN_SWAP32:
+ SWAPN(32);
+ break;
+ case FASM_TOKEN_SWAP64:
+ SWAPN(64);
+ break;
+ case FASM_TOKEN_DROP8:
+ DROPN(8);
+ break;
+ case FASM_TOKEN_DROP16:
+ DROPN(16);
+ break;
+ case FASM_TOKEN_DROP32:
+ DROPN(32);
+ break;
+ case FASM_TOKEN_DROP64:
+ DROPN(64);
+ break;
+ case FASM_TOKEN_ADD_I8:
+ ADD(uint8_t, 8);
+ break;
+ case FASM_TOKEN_ADD_I16:
+ ADD(uint16_t, 16);
+ break;
+ case FASM_TOKEN_ADD_I32:
+ ADD(uint32_t, 32);
+ break;
+ case FASM_TOKEN_ADD_I64:
+ ADD(uint64_t, 64);
+ break;
+ case FASM_TOKEN_ADD_F32:
+ ADD(float, 32);
+ break;
+ case FASM_TOKEN_ADD_F64:
+ ADD(double, 64);
+ break;
+ case FASM_TOKEN_SUB_I8:
+ SUB(uint8_t, 8);
+ break;
+ case FASM_TOKEN_SUB_I16:
+ SUB(uint16_t, 16);
+ break;
+ case FASM_TOKEN_SUB_I32:
+ SUB(uint32_t, 32);
+ break;
+ case FASM_TOKEN_SUB_I64:
+ SUB(uint64_t, 64);
+ break;
+ case FASM_TOKEN_SUB_F32:
+ SUB(float, 32);
+ break;
+ case FASM_TOKEN_SUB_F64:
+ SUB(double, 64);
+ break;
+ case FASM_TOKEN_NEG_I8:
+ NEG(int8_t, 8);
+ break;
+ case FASM_TOKEN_NEG_I16:
+ NEG(int16_t, 16);
+ break;
+ case FASM_TOKEN_NEG_I32:
+ NEG(int32_t, 32);
+ break;
+ case FASM_TOKEN_NEG_I64:
+ NEG(int64_t, 64);
+ break;
+ case FASM_TOKEN_NEG_F32:
+ NEG(float, 32);
+ break;
+ case FASM_TOKEN_NEG_F64:
+ NEG(double, 64);
+ break;
+ case FASM_TOKEN_MUL_I8:
+ MUL(int8_t, 8);
+ break;
+ case FASM_TOKEN_MUL_I16:
+ MUL(int16_t, 16);
+ break;
+ case FASM_TOKEN_MUL_I32:
+ MUL(int32_t, 32);
+ break;
+ case FASM_TOKEN_MUL_I64:
+ MUL(int64_t, 64);
+ break;
+ case FASM_TOKEN_MUL_U8:
+ MUL(uint8_t, 8);
+ break;
+ case FASM_TOKEN_MUL_U16:
+ MUL(uint16_t, 16);
+ break;
+ case FASM_TOKEN_MUL_U32:
+ MUL(uint32_t, 32);
+ break;
+ case FASM_TOKEN_MUL_U64:
+ MUL(uint64_t, 64);
+ break;
+ case FASM_TOKEN_MUL_F32:
+ MUL(float, 32);
+ break;
+ case FASM_TOKEN_MUL_F64:
+ MUL(double, 64);
+ break;
+ case FASM_TOKEN_DIV_I8:
+ DIV(int8_t, 8);
+ break;
+ case FASM_TOKEN_DIV_I16:
+ DIV(int16_t, 16);
+ break;
+ case FASM_TOKEN_DIV_I32:
+ DIV(int32_t, 32);
+ break;
+ case FASM_TOKEN_DIV_I64:
+ DIV(int64_t, 64);
+ break;
+ case FASM_TOKEN_DIV_U8:
+ DIV(uint8_t, 8);
+ break;
+ case FASM_TOKEN_DIV_U16:
+ DIV(uint16_t, 16);
+ break;
+ case FASM_TOKEN_DIV_U32:
+ DIV(uint32_t, 32);
+ break;
+ case FASM_TOKEN_DIV_U64:
+ DIV(uint64_t, 64);
+ break;
+ case FASM_TOKEN_DIV_F32:
+ DIV(float, 32);
+ break;
+ case FASM_TOKEN_DIV_F64:
+ DIV(double, 64);
+ break;
+ case FASM_TOKEN_REM_I8:
+ REM(int8_t, 8);
+ break;
+ case FASM_TOKEN_REM_I16:
+ REM(int16_t, 16);
+ break;
+ case FASM_TOKEN_REM_I32:
+ REM(int32_t, 32);
+ break;
+ case FASM_TOKEN_REM_I64:
+ REM(int64_t, 64);
+ break;
+ case FASM_TOKEN_REM_U8:
+ REM(uint8_t, 8);
+ break;
+ case FASM_TOKEN_REM_U16:
+ REM(uint16_t, 16);
+ break;
+ case FASM_TOKEN_REM_U32:
+ REM(uint32_t, 32);
+ break;
+ case FASM_TOKEN_REM_U64:
+ REM(uint64_t, 64);
+ break;
+ case FASM_TOKEN_CAST_I8_I64:
+ CAST(int8_t, 8, int64_t, 64);
+ break;
+ case FASM_TOKEN_CAST_I16_I64:
+ CAST(int16_t, 16, int64_t, 64);
+ break;
+ case FASM_TOKEN_CAST_I32_I64:
+ CAST(int32_t, 32, int64_t, 64);
+ break;
+ case FASM_TOKEN_CAST_I64_I8:
+ CAST(int64_t, 64, int8_t, 8);
+ break;
+ case FASM_TOKEN_CAST_I64_I16:
+ CAST(int64_t, 64, int16_t, 16);
+ break;
+ case FASM_TOKEN_CAST_I64_I32:
+ CAST(int64_t, 64, int32_t, 32);
+ break;
+ case FASM_TOKEN_CAST_F64_I64:
+ CAST(double, 64, int64_t, 64);
+ break;
+ case FASM_TOKEN_CAST_I64_F64:
+ CAST(int64_t, 64, double, 64);
+ break;
+ case FASM_TOKEN_CAST_U8_U64:
+ CAST(uint8_t, 8, uint64_t, 64);
+ break;
+ case FASM_TOKEN_CAST_U16_U64:
+ CAST(uint16_t, 16, uint64_t, 64);
+ break;
+ case FASM_TOKEN_CAST_U32_U64:
+ CAST(uint32_t, 32, uint64_t, 64);
+ break;
+ case FASM_TOKEN_CAST_U64_U8:
+ CAST(uint64_t, 64, uint8_t, 8);
+ break;
+ case FASM_TOKEN_CAST_U64_U16:
+ CAST(uint64_t, 64, uint16_t, 16);
+ break;
+ case FASM_TOKEN_CAST_U64_U32:
+ CAST(uint64_t, 64, uint32_t, 32);
+ break;
+ case FASM_TOKEN_CAST_F64_U64:
+ CAST(double, 64, uint64_t, 64);
+ break;
+ case FASM_TOKEN_CAST_U64_F64:
+ CAST(uint64_t, 64, double, 64);
+ break;
+ case FASM_TOKEN_CAST_F32_F64:
+ CAST(float, 32, double, 64);
+ break;
+ case FASM_TOKEN_CAST_F64_F32:
+ CAST(double, 64, float, 32);
+ break;
+ case FASM_TOKEN_JUMP:
+ ip = (uint8_t *)popFromStack64Bits(&stack, &stack_size, &stack_filled);
+ break;
+ case FASM_TOKEN_JZ_I8:
+ COND_JUMP(int8_t, 8, ==);
+ break;
+ case FASM_TOKEN_JNZ_I8:
+ COND_JUMP(int8_t, 8, !=);
+ break;
+ case FASM_TOKEN_JN_I8:
+ COND_JUMP(int8_t, 8, <);
+ break;
+ case FASM_TOKEN_JNN_I8:
+ COND_JUMP(int8_t, 8, >=);
+ break;
+ case FASM_TOKEN_JP_I8:
+ COND_JUMP(int8_t, 8, >);
+ break;
+ case FASM_TOKEN_JNP_I8:
+ COND_JUMP(int8_t, 8, <=);
+ break;
+ case FASM_TOKEN_JZ_I16:
+ COND_JUMP(int16_t, 16, ==);
+ break;
+ case FASM_TOKEN_JNZ_I16:
+ COND_JUMP(int16_t, 16, !=);
+ break;
+ case FASM_TOKEN_JN_I16:
+ COND_JUMP(int16_t, 16, <);
+ break;
+ case FASM_TOKEN_JNN_I16:
+ COND_JUMP(int16_t, 16, >=);
+ break;
+ case FASM_TOKEN_JP_I16:
+ COND_JUMP(int16_t, 16, >);
+ break;
+ case FASM_TOKEN_JNP_I16:
+ COND_JUMP(int16_t, 16, <=);
+ break;
+ case FASM_TOKEN_JZ_I32:
+ COND_JUMP(int32_t, 32, ==);
+ break;
+ case FASM_TOKEN_JNZ_I32:
+ COND_JUMP(int32_t, 32, !=);
+ break;
+ case FASM_TOKEN_JN_I32:
+ COND_JUMP(int32_t, 32, <);
+ break;
+ case FASM_TOKEN_JNN_I32:
+ COND_JUMP(int32_t, 32, >=);
+ break;
+ case FASM_TOKEN_JP_I32:
+ COND_JUMP(int32_t, 32, >);
+ break;
+ case FASM_TOKEN_JNP_I32:
+ COND_JUMP(int32_t, 32, <=);
+ break;
+ case FASM_TOKEN_JZ_I64:
+ COND_JUMP(int64_t, 64, ==);
+ break;
+ case FASM_TOKEN_JNZ_I64:
+ COND_JUMP(int64_t, 64, !=);
+ break;
+ case FASM_TOKEN_JN_I64:
+ COND_JUMP(int64_t, 64, <);
+ break;
+ case FASM_TOKEN_JNN_I64:
+ COND_JUMP(int64_t, 64, >=);
+ break;
+ case FASM_TOKEN_JP_I64:
+ COND_JUMP(int64_t, 64, >);
+ break;
+ case FASM_TOKEN_JNP_I64:
+ COND_JUMP(int64_t, 64, <=);
+ break;
+ case FASM_TOKEN_JZ_F32:
+ COND_JUMP(float, 32, ==);
+ break;
+ case FASM_TOKEN_JNZ_F32:
+ COND_JUMP(float, 32, !=);
+ break;
+ case FASM_TOKEN_JN_F32:
+ COND_JUMP(float, 32, <);
+ break;
+ case FASM_TOKEN_JNN_F32:
+ COND_JUMP(float, 32, >=);
+ break;
+ case FASM_TOKEN_JP_F32:
+ COND_JUMP(float, 32, >);
+ break;
+ case FASM_TOKEN_JNP_F32:
+ COND_JUMP(float, 32, <=);
+ break;
+ case FASM_TOKEN_JZ_F64:
+ COND_JUMP(double, 64, ==);
+ break;
+ case FASM_TOKEN_JNZ_F64:
+ COND_JUMP(double, 64, !=);
+ break;
+ case FASM_TOKEN_JN_F64:
+ COND_JUMP(double, 64, <);
+ break;
+ case FASM_TOKEN_JNN_F64:
+ COND_JUMP(double, 64, >=);
+ break;
+ case FASM_TOKEN_JP_F64:
+ COND_JUMP(double, 64, >);
+ break;
+ case FASM_TOKEN_JNP_F64:
+ COND_JUMP(double, 64, <=);
+ break;
+ case FASM_TOKEN_ALLOC_HEAP:
+ pushToStack64Bits(&stack, &stack_size, &stack_filled,
+ (uint64_t)a404m_malloc(popFromStack64Bits(
+ &stack, &stack_size, &stack_filled)));
+ break;
+ case FASM_TOKEN_ALLOC_STACK:
+ functions[functions_index].stack_size =
+ popFromStack64Bits(&stack, &stack_size, &stack_filled);
+ functions[functions_index].stack =
+ a404m_malloc(functions[functions_index].stack_size);
+ break;
+ case FASM_TOKEN_FREE_HEAP:
+ free((void *)popFromStack64Bits(&stack, &stack_size, &stack_filled));
+ break;
+ case FASM_TOKEN_GET_STACK_ADDRESS:
+ pushToStack64Bits(&stack, &stack_size, &stack_filled,
+ (uint64_t)functions[functions_index].stack);
+ break;
+ case FASM_TOKEN_GET_GLOBAL_ADDRESS:
+ pushToStack64Bits(&stack, &stack_size, &stack_filled, (uint64_t)data);
+ break;
+ case FASM_TOKEN_CALL: {
+ uint8_t *const newIp =
+ (uint8_t *)popFromStack64Bits(&stack, &stack_size, &stack_filled);
+ ++functions_index;
+ if (functions_index == functions_size) {
+ functions_size += functions_size / 2 + 1;
+ functions =
+ a404m_realloc(functions, functions_size * sizeof(*functions));
+ }
+ FasmFunction function = {
+ .returnTo = ip,
+ .stack = a404m_malloc(0),
+ .stack_size = 0,
+ };
+ functions[functions_index] = function;
+ ip = newIp;
+ } break;
+ case FASM_TOKEN_RET: {
+ FasmFunction function = functions[functions_index];
+ free(function.stack);
+ ip = function.returnTo;
+ --functions_index;
+ if (functions_index + sizeof(*functions) < functions_size / 2) {
+ functions_size = functions_size / 2;
+ functions =
+ a404m_realloc(functions, functions_size * sizeof(*functions));
+ }
+ } break;
+ case FASM_TOKEN_SYSCALL: {
+ switch ((FasmSyscall)popFromStack8Bits(&stack, &stack_size,
+ &stack_filled)) {
+ case FASM_SYSCALL_READ: {
+ uint32_t fd =
+ popFromStack32Bits(&stack, &stack_size, &stack_filled);
+ int8_t *buf = (int8_t *)popFromStack64Bits(&stack, &stack_size,
+ &stack_filled);
+ uint64_t count =
+ popFromStack64Bits(&stack, &stack_size, &stack_filled);
+ syscall(SYS_read, fd, buf, count);
+ } break;
+ case FASM_SYSCALL_WRITE: {
+ uint32_t fd =
+ popFromStack32Bits(&stack, &stack_size, &stack_filled);
+ int8_t *buf = (int8_t *)popFromStack64Bits(&stack, &stack_size,
+ &stack_filled);
+ uint64_t count =
+ popFromStack64Bits(&stack, &stack_size, &stack_filled);
+ syscall(SYS_write, fd, buf, count);
+ } break;
+ case FASM_SYSCALL_OPEN: {
+ int8_t *filename = (int8_t *)popFromStack64Bits(&stack, &stack_size,
+ &stack_filled);
+ uint32_t flags =
+ popFromStack32Bits(&stack, &stack_size, &stack_filled);
+ uint32_t mode =
+ popFromStack32Bits(&stack, &stack_size, &stack_filled);
+ syscall(SYS_open, filename, flags, mode);
+ } break;
+ case FASM_SYSCALL_CLOSE: {
+ uint32_t fd =
+ popFromStack32Bits(&stack, &stack_size, &stack_filled);
+ syscall(SYS_close, fd);
+ } break;
+ case FASM_SYSCALL_EXIT:
+ for (size_t i = functions_index; i != (size_t)-1; ++i) {
+ free(functions[i].stack);
+ }
+ const uint32_t status =
+ popFromStack32Bits(&stack, &stack_size, &stack_filled);
+ free(functions);
+ free(stack);
+ free(data);
+ return status;
+ }
+ } break;
+ case FASM_TOKEN_DEFINE_BYTE:
+ case FASM_TOKEN_DEFINE_WORD:
+ case FASM_TOKEN_DEFINE_DWORD:
+ case FASM_TOKEN_DEFINE_QWORD:
+ case FASM_TOKEN_NONE:
+ default:
+ fprintf(stderr, "Bad fasm instruction %d", instruction);
+ exit(1);
+ }
+ }
+}
+
+#define getNextNBits(bits) \
+ uint##bits##_t getNext##bits##Bits(uint8_t **pos) { \
+ uint##bits##_t *p = *((uint##bits##_t **)pos); \
+ pos += sizeof(*p); \
+ return *p; \
+ }
+
+getNextNBits(8);
+getNextNBits(16);
+getNextNBits(32);
+getNextNBits(64);
+
+#define pushToStackNBits(bits) \
+ void pushToStack##bits##Bits(uint8_t **stack, size_t *stack_size, \
+ size_t *stack_filled, uint##bits##_t value) { \
+ const size_t new_stack_size = *stack_filled + sizeof(value); \
+ if (new_stack_size >= *stack_size) { \
+ *stack_size = new_stack_size + new_stack_size / 2 + 1; \
+ *stack = a404m_realloc(*stack, *stack_size); \
+ } \
+ *((uint##bits##_t *)(*stack + *stack_filled)) = value; \
+ *stack_filled = new_stack_size; \
+ }
+pushToStackNBits(8);
+pushToStackNBits(16);
+pushToStackNBits(32);
+pushToStackNBits(64);
+
+#define popFromStackNBit(bits) \
+ uint##bits##_t popFromStack##bits##Bits(uint8_t **stack, size_t *stack_size, \
+ size_t *stack_filled) { \
+ uint##bits##_t value; \
+ *stack_filled -= sizeof(value); \
+ value = *((uint##bits##_t *)(*stack + *stack_filled)); \
+ if (*stack_filled < *stack_size / 2) { \
+ *stack_size = *stack_filled; \
+ *stack = a404m_realloc(*stack, *stack_size); \
+ } \
+ return value; \
+ }
+popFromStackNBit(8);
+popFromStackNBit(16);
+popFromStackNBit(32);
+popFromStackNBit(64);
diff --git a/src/fasm/runner/runner.h b/src/fasm/runner/runner.h
new file mode 100644
index 0000000..0dfa338
--- /dev/null
+++ b/src/fasm/runner/runner.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <fasm/code_generator/code_generator.h>
+#include <stdint.h>
+
+typedef struct FasmFunction {
+ uint8_t *returnTo;
+ uint8_t *stack;
+ size_t stack_size;
+}FasmFunction;
+
+extern int fasmRunner(ByteCode bytecode);
+
+#define getNextNBitsHeader(bits) \
+ extern uint##bits##_t getNext##bits##Bits(uint8_t **pos)
+getNextNBitsHeader(8);
+getNextNBitsHeader(16);
+getNextNBitsHeader(32);
+getNextNBitsHeader(64);
+
+#define pushToStackNBitsHeader(bits) \
+ extern void pushToStack##bits##Bits(uint8_t **stack, size_t *stack_size, \
+ size_t *stack_filled, \
+ uint##bits##_t value)
+pushToStackNBitsHeader(8);
+pushToStackNBitsHeader(16);
+pushToStackNBitsHeader(32);
+pushToStackNBitsHeader(64);
+
+#define popFromStackNBitsHeader(bits) \
+ extern uint##bits##_t popFromStack##bits##Bits( \
+ uint8_t **stack, size_t *stack_size, size_t *stack_filled)
+popFromStackNBitsHeader(8);
+popFromStackNBitsHeader(16);
+popFromStackNBitsHeader(32);
+popFromStackNBitsHeader(64);