Browse Source

Basic byte code executor

Kajetan Johannes Hammerle 2 tuần trước cách đây
mục cha
commit
c426c0fc1e
8 tập tin đã thay đổi với 232 bổ sung3 xóa
  1. 1 1
      .clangd
  2. 2 0
      CMakeLists.txt
  3. 75 0
      src/Code.c
  4. 24 0
      src/Code.h
  5. 14 0
      src/Constants.h
  6. 67 2
      src/Main.c
  7. 20 0
      src/Values.c
  8. 29 0
      src/Values.h

+ 1 - 1
.clangd

@@ -1,3 +1,3 @@
 CompileFlags:
-  Add: [-ferror-limit=0]
+  Add: [-ferror-limit=0, -std=c23]
   CompilationDatabase: ./build_debug/

+ 2 - 0
CMakeLists.txt

@@ -5,6 +5,8 @@ set(CMAKE_C_STANDARD 23)
 
 set(SRC
     "src/Main.c"
+    "src/Code.c"
+    "src/Values.c"
 )
 
 set(COMPILER_ARGUMENTS

+ 75 - 0
src/Code.c

@@ -0,0 +1,75 @@
+#include "Code.h"
+
+#include <string.h>
+
+static u8 code[MAX_CODE];
+static size_t codeIndex = 0;
+static size_t codeExecutionIndex = 0;
+
+static bool pushU8(u8 u) {
+    if(codeIndex >= MAX_CODE) {
+        return true;
+    }
+    code[codeIndex++] = u;
+    return false;
+}
+
+static bool push(const void* p, size_t n) {
+    if(codeIndex + n >= MAX_CODE) {
+        return true;
+    }
+    memcpy(code + codeIndex, p, n);
+    codeIndex += n;
+    return false;
+}
+
+bool pushInstruction(Instruction i) {
+    return pushU8(i);
+}
+
+bool pushI64(i64 i) {
+    return push(&i, sizeof(i));
+}
+
+bool pushSize(size_t i) {
+    return push(&i, sizeof(i));
+}
+
+bool pushConstantString(const char* c) {
+    size_t n = strlen(c) + 1;
+    return pushSize(n) || push(c, n);
+}
+
+Instruction readInstruction() {
+    return codeExecutionIndex < codeIndex ? code[codeExecutionIndex++] : STOP;
+}
+
+static void read(void* p, size_t n) {
+    if(codeExecutionIndex + n <= codeIndex) {
+        memcpy(p, code + codeExecutionIndex, n);
+        codeExecutionIndex += n;
+    }
+}
+
+i64 readI64() {
+    i64 i;
+    read(&i, sizeof(i));
+    return i;
+}
+
+size_t readSize() {
+    size_t i;
+    read(&i, sizeof(i));
+    return i;
+}
+
+const char* readConstantString() {
+    size_t n = readSize();
+    if(codeExecutionIndex + n <= codeIndex &&
+       code[codeExecutionIndex + n - 1] == '\0') {
+        const char* s = (char*)(code + codeExecutionIndex);
+        codeExecutionIndex += n;
+        return s;
+    }
+    return "";
+}

+ 24 - 0
src/Code.h

@@ -0,0 +1,24 @@
+#ifndef BASIC_CODE_H
+#define BASIC_CODE_H
+
+#include "Constants.h"
+
+typedef enum : u8 {
+    ADD,
+    PUSH_CONSTANT_STRING,
+    PUSH_INT,
+    PRINT,
+    STOP
+} Instruction;
+
+[[nodiscard]] bool pushInstruction(Instruction i);
+[[nodiscard]] bool pushI64(i64 i);
+[[nodiscard]] bool pushSize(size_t i);
+[[nodiscard]] bool pushConstantString(const char* c);
+
+Instruction readInstruction();
+i64 readI64();
+size_t readSize();
+const char* readConstantString();
+
+#endif

+ 14 - 0
src/Constants.h

@@ -0,0 +1,14 @@
+#ifndef BASIC_CONSTANTS_H
+#define BASIC_CONSTANTS_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef uint64_t u64;
+typedef uint8_t u8;
+typedef int64_t i64;
+
+[[maybe_unused]] constexpr size_t MAX_CODE = 1024 * 1024 * 2;
+[[maybe_unused]] constexpr size_t MAX_VALUES = 1024;
+
+#endif

+ 67 - 2
src/Main.c

@@ -1,6 +1,71 @@
+#include <stdint.h>
 #include <stdio.h>
 
-int main() {
-    puts("hi");
+#include "Code.h"
+#include "Values.h"
+
+#define POP_VALUE(name) \
+    Value name;         \
+    if(popValue(&name)) \
+    return true
+
+static bool iAdd() {
+    POP_VALUE(a);
+    POP_VALUE(b);
+    return pushValue(INT_VALUE(a.intValue + b.intValue));
+}
+
+static bool iPushConstantString() {
+    return pushValue(CSTRING_VALUE(readConstantString()));
+}
+
+static bool iPushInt() {
+    return pushValue(INT_VALUE(readI64()));
+}
+
+static bool iPrint() {
+    POP_VALUE(a);
+    switch(a.type) {
+        case INT64: printf("%ld\n", a.intValue); break;
+        case CONSTANT_STRING: printf("%s\n", a.constantStringValue); break;
+    }
+    return false;
+}
+
+static bool execute(Instruction command) {
+    switch(command) {
+        case ADD: return iAdd();
+        case PUSH_CONSTANT_STRING: return iPushConstantString();
+        case PUSH_INT: return iPushInt();
+        case PRINT: return iPrint();
+        case STOP: return true;
+    }
+    return false;
+}
+
+int main(void) {
+    (void)pushInstruction(PUSH_INT);
+    (void)pushI64(16);
+    (void)pushInstruction(PUSH_INT);
+    (void)pushI64(50);
+    (void)pushInstruction(ADD);
+    (void)pushInstruction(PUSH_INT);
+    (void)pushI64(40);
+    (void)pushInstruction(ADD);
+    (void)pushInstruction(PRINT);
+    (void)pushInstruction(PUSH_CONSTANT_STRING);
+    (void)pushConstantString("Das ist ein Test");
+    (void)pushInstruction(PRINT);
+
+    while(!execute(readInstruction())) {}
+    // char line[256];
+    // while(true) {
+    //     fgets(line, sizeof(line), stdin);
+    //     if(strcmp(line, "quit\n") == 0) {
+    //         break;
+    //     }
+    //     puts(line);
+    // }
+    // puts("quit");
     return 0;
 }

+ 20 - 0
src/Values.c

@@ -0,0 +1,20 @@
+#include "Values.h"
+
+static Value valueStack[MAX_VALUES];
+static size_t valueStackIndex = 0;
+
+bool pushValue(Value v) {
+    if(valueStackIndex >= MAX_VALUES) {
+        return true;
+    }
+    valueStack[valueStackIndex++] = v;
+    return false;
+}
+
+bool popValue(Value* v) {
+    if(valueStackIndex <= 0) {
+        return true;
+    }
+    *v = valueStack[--valueStackIndex];
+    return false;
+}

+ 29 - 0
src/Values.h

@@ -0,0 +1,29 @@
+#ifndef BASIC_VALUES_H
+#define BASIC_VALUES_H
+
+#include "Constants.h"
+
+typedef enum : u8 { INT64, CONSTANT_STRING } ValueType;
+
+typedef struct {
+    ValueType type;
+    u8 reserved1;
+    u8 reserved2;
+    u8 reserved3;
+
+    union {
+        i64 intValue;
+        const char* constantStringValue;
+    };
+} Value;
+
+static_assert(sizeof(Value) == 16, "invalid Value size");
+
+#define INT_VALUE(value) ((Value){.type = INT64, .intValue = (value)})
+#define CSTRING_VALUE(value)                                           \
+    ((Value){.type = CONSTANT_STRING, .constantStringValue = (value)})
+
+[[nodiscard]] bool pushValue(Value v);
+[[nodiscard]] bool popValue(Value* v);
+
+#endif