Explorar o código

Heap allocator

Kajetan Johannes Hammerle hai 2 semanas
pai
achega
7cfcc05c82
Modificáronse 6 ficheiros con 159 adicións e 33 borrados
  1. 1 0
      CMakeLists.txt
  2. 5 0
      src/Code.h
  3. 23 0
      src/Main.c
  4. 119 0
      src/Memory.c
  5. 11 0
      src/Memory.h
  6. 0 33
      src/Tokenizer.c

+ 1 - 0
CMakeLists.txt

@@ -12,6 +12,7 @@ set(SRC
     "src/Compiler.c"
     "src/Tokenizer.c"
     "src/Buffer.c"
+    "src/Memory.c"
 )
 
 set(COMPILER_ARGUMENTS

+ 5 - 0
src/Code.h

@@ -1,6 +1,7 @@
 #ifndef BASIC_CODE_H
 #define BASIC_CODE_H
 
+#include "Buffer.h"
 #include "Types.h"
 
 typedef enum : u8 {
@@ -13,6 +14,10 @@ typedef enum : u8 {
     STOP
 } Instruction;
 
+// typedef struct {
+//     Buffer code;
+// } Code;
+
 void codeReset();
 void codeRun();
 

+ 23 - 0
src/Main.c

@@ -1,8 +1,10 @@
 #include <stdint.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "Code.h"
 #include "Compiler.h"
+#include "Memory.h"
 #include "Tokenizer.h"
 
 static u8 tokens[1000];
@@ -21,6 +23,27 @@ int main(int argCount, const char** args) {
         return 0;
     }
 
+    static char heap[100];
+    memoryInit(heap, sizeof(heap));
+    memoryDump();
+
+    char* c1 = memoryAllocate(16);
+    char* c2 = memoryAllocate(22);
+    char* c3 = memoryAllocate(32);
+    if(c1 == nullptr || c2 == nullptr || c3 == nullptr) {
+        return 0;
+    }
+    memset(c1, 1, 16);
+    memset(c2, 2, 22);
+    memset(c3, 3, 32);
+    memoryDump();
+    memoryFree(c2);
+    memoryDump();
+    memoryFree(c3);
+    memoryDump();
+    memoryFree(c1);
+    memoryDump();
+
     Tokenizer t;
     if(tokenizerInit(&t, args[1], tokens, sizeof(tokens))) {
         puts(tokenizerGetError(&t));

+ 119 - 0
src/Memory.c

@@ -0,0 +1,119 @@
+#include "Memory.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct {
+    u32 units;
+    i32 next;
+} Slot;
+
+static Slot* memory = nullptr;
+static u32 maxUnits = 0;
+static Slot baseSlot = {.units = 0, .next = -1};
+static Slot* slots = &baseSlot;
+static constexpr i32 CANARY = (i32)0xEFBEADDE;
+
+static i32 memoryGetSlotIndex(const Slot* s) {
+    return (i32)(s - memory);
+}
+
+void memoryInit(void* p, u32 n) {
+    u32 offset = (u64)p % sizeof(Slot);
+    if(offset > 0) {
+        offset = (u32)sizeof(Slot) - offset;
+    }
+
+    memory = (Slot*)(void*)((char*)p + offset);
+    maxUnits = (n - offset) / sizeof(Slot);
+
+    Slot* s = memory;
+    s->next = -1;
+    s->units = maxUnits;
+    slots->next = 0;
+}
+
+static Slot* memoryNextSlot(const Slot* s) {
+    if(s->next == -1) {
+        return nullptr;
+    }
+    return memory + s->next;
+}
+
+void* memoryAllocate(size_t bytes) {
+    if(bytes == 0) {
+        return nullptr;
+    }
+    u32 units = (u32)((bytes + sizeof(Slot) - 1) / sizeof(Slot) + 1);
+    if(units > maxUnits) {
+        return nullptr;
+    }
+    Slot* previous = nullptr;
+    Slot* current = slots;
+    while(current != nullptr) {
+        if(current->units >= units) {
+            break;
+        }
+        previous = current;
+        current = memoryNextSlot(current);
+    }
+    if(current == nullptr) {
+        return nullptr;
+    }
+    if(current->units == units) {
+        previous->next = current->next;
+    } else {
+        Slot* newSlot = current + units;
+        newSlot->next = current->next;
+        newSlot->units = current->units - units;
+        previous->next = memoryGetSlotIndex(newSlot);
+    }
+    current->next = CANARY;
+    current->units = units;
+    return current + 1;
+}
+
+void memoryFree(void* p) {
+    Slot* s = (Slot*)p - 1;
+    if(s->next != CANARY) {
+        fprintf(stderr, "free with corupt canary\n");
+        abort();
+    }
+    Slot* previous = slots;
+    Slot* current = memoryNextSlot(slots);
+    while(current != nullptr && current < s) {
+        previous = current;
+        current = memoryNextSlot(current);
+    }
+
+    if(current == nullptr) {
+        s->next = -1;
+    } else if(s + s->units == current) {
+        s->units += current->units;
+        s->next = current->next;
+    } else {
+        s->next = memoryGetSlotIndex(current);
+    }
+
+    if(previous + previous->units == s) {
+        previous->units += s->units;
+        previous->next = s->next;
+    } else {
+        previous->next = memoryGetSlotIndex(s);
+    }
+}
+
+void memoryDump() {
+    for(size_t i = 0; i < maxUnits * sizeof(Slot); i++) {
+        printf("%02x", (unsigned)((char*)memory)[i] & 0xFF);
+        if((i + 1) % 30 == 0) {
+            putchar('\n');
+        }
+    }
+    putchar('\n');
+    Slot* current = memoryNextSlot(slots);
+    while(current != nullptr) {
+        printf("Free slot %u\n", current->units);
+        current = memoryNextSlot(current);
+    }
+}

+ 11 - 0
src/Memory.h

@@ -0,0 +1,11 @@
+#ifndef BASIC_MEMORY_H
+#define BASIC_MEMORY_H
+
+#include "Types.h"
+
+void memoryInit(void* p, u32 n);
+void* memoryAllocate(size_t bytes);
+void memoryFree(void* p);
+void memoryDump();
+
+#endif

+ 0 - 33
src/Tokenizer.c

@@ -157,39 +157,6 @@ static void tokenizerParseLine(Tokenizer* t) {
     tokenizerParseLineString(t, line);
 }
 
-//[[noreturn]] static void unexpectedToken(Token t) {
-//    switch(t) {
-//        case LITERAL:
-//            THROW_ERROR(
-//                "Unexpected literal(%s) on line %zu", readString(),
-//                lineCounter);
-//            break;
-//        case INT64:
-//            THROW_ERROR(
-//                "Unexpected int(%ld) on line %zu", readInt64(), lineCounter);
-//            break;
-//        case DOUBLE:
-//            THROW_ERROR(
-//                "Unexpected double(%lf) on line %zu", readDouble(),
-//                lineCounter);
-//            break;
-//        case STRING:
-//            THROW_ERROR(
-//                "Unexpected string(%s) on line %zu", readString(),
-//                lineCounter);
-//            break;
-//        case PLUS:
-//            THROW_ERROR("Unexpected plus on line %zu", lineCounter);
-//            break;
-//        case NEWLINE:
-//            THROW_ERROR("Unexpected newline on line %zu", lineCounter);
-//            break;
-//        case END: THROW_ERROR("Unexpected end on line %zu", lineCounter);
-//        break;
-//    }
-//    THROW_ERROR("Unexpected unknown token on line %zu", lineCounter);
-//}
-
 static const char* tokenizerReadString(Tokenizer* t) {
     const char* c = (char*)(t->buffer.data + t->buffer.readIndex);
     i8 i = 1;