From addd54dc31603dc204773d3108dba4e000cd7657 Mon Sep 17 00:00:00 2001
From: A404M <ahmadmahmoudiprogrammer@gmail.com>
Date: Tue, 8 Oct 2024 04:16:27 +0330
Subject: added fasm support added compiler options tried to compile to fasm
 first

---
 src/fasm/runner/runner.c | 646 +++++++++++++++++++++++++++++++++++++++++++++++
 src/fasm/runner/runner.h |  36 +++
 2 files changed, 682 insertions(+)
 create mode 100644 src/fasm/runner/runner.c
 create mode 100644 src/fasm/runner/runner.h

(limited to 'src/fasm/runner')

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);
-- 
cgit v1.2.3