From 57ee82d0834675710e8ac235c71be7504ef5cf0d Mon Sep 17 00:00:00 2001
From: attilavs2 <whahou072@icloud.com>
Date: Sun, 16 Mar 2025 21:56:51 +0100
Subject: [PATCH] Tests + fixes

---
 TODO.md           |   3 ++
 src/exec_common.c | 128 +++++++++++++++++++++++++++++++---------------
 src/exec_common.h |  12 +++--
 src/parser.y      |   4 +-
 src/tests.c       |  54 +++++++++++++++++++
 5 files changed, 153 insertions(+), 48 deletions(-)

diff --git a/TODO.md b/TODO.md
index be18c9c..3b3ff62 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,3 +1,6 @@
+tmp:
+  - fix realloc
+
 - Benchmarks
 - Tests
 - Rework assign/call to work better
diff --git a/src/exec_common.c b/src/exec_common.c
index 27b9a70..981d7ed 100644
--- a/src/exec_common.c
+++ b/src/exec_common.c
@@ -36,6 +36,8 @@ typedef struct {
 
 } AllocBlock;
 
+#define EXT_BLOCK 4096
+
 void *internal_buf;
 AllocBlock *blocks;
 u32 *usage; // bitmap for usage, by 8byte chunks
@@ -70,48 +72,14 @@ int evaluate(Value val){
   }
 }
 
-int alloc_init(){
-  internal_buf = malloc(4096);
-  blocks = malloc(sizeof(AllocBlock));
-  block_count = 0;
-  usage = malloc(sizeof(u32)*4096/32/8);
-  if(!internal_buf || !blocks || !usage)
+int alloc_extend(u32 size){
+  size = (size/EXT_BLOCK+1)*EXT_BLOCK;
+  internal_buf = realloc(internal_buf, internal_size+size);
+  usage = realloc(usage, sizeof(u32)*(internal_size+size)/32/8);
+  if(!internal_buf || !usage)
     return 1;
-  memset(usage, 0, sizeof(u32)*4096/32/8); 
-  return 0;
-}
-
-u32 flisp_alloc(size_t size){
-  u32 pos = 32;
-  u32 curr_free = 0;
-  while(pos < internal_size){
-    if(usage[pos/32/8]){
-      for(int i = 0; i < 32; i++){
-        if((usage[pos/32/8]>>i) & 1)
-          curr_free = 0;
-        else
-          curr_free+=8;
-      }
-    }
-    else {
-      curr_free += 32*8;
-    }
-    if(curr_free >= size){
-      blocks = realloc(blocks, sizeof(AllocBlock)*(block_count+1));
-      if(!blocks)
-        return 0;
-      AllocBlock *block = &blocks[block_count++];
-      block->pos = pos - curr_free;
-      block->size = size;
-      for(u32 i = block->pos; i < block->pos+size; i++){
-        usage[i/32/8] |= 1<<(i%(32*8));
-      }
-      // Unvirtualize the memory
-      memset(get_addr(block->pos),0xB00B5069,size);
-      return block->pos;
-    }
-    pos++;
-  }
+  memset(usage+(internal_size/32/8), 0, sizeof(u32)*size/32/8);
+  internal_size += size;
   return 0;
 }
 
@@ -121,10 +89,86 @@ int block_cmpfunc(const void *_a, const void *_b){
   return b->pos - a->pos;
 }
 
-void flisp_free(u32 pos){
+AllocBlock *get_block(u32 pos){
   AllocBlock tmp = {.pos = pos};
   AllocBlock *ret = bsearch(&tmp, blocks, block_count, sizeof(AllocBlock),
                               block_cmpfunc);
+  return ret;
+}
+
+int alloc_init(){
+  blocks = malloc(sizeof(AllocBlock));
+  block_count = 0;
+  internal_buf = NULL;
+  internal_size = 0;
+  usage = NULL;
+  if(!blocks || alloc_extend(EXT_BLOCK))
+    return 1;
+  return 0;
+}
+
+void alloc_clean(){
+  free(internal_buf);
+  free(blocks);
+  free(usage);
+}
+
+u32 flisp_alloc(u32 size){
+  u32 pos = 32;
+  u32 curr_free = 0;
+  while(pos < internal_size){
+    if(usage[pos/32/8]){
+      for(int i = 0; i < 32; i++){
+        if((usage[pos/32/8]>>i) & 1)
+          curr_free = 0;
+        else
+          curr_free+=8;
+        pos+=8;
+        if(curr_free >= size)
+          break;
+      }
+    }
+    else {
+      curr_free += 32*8;
+      pos+=32*8;
+    }
+    if(curr_free >= size){
+      blocks = realloc(blocks, sizeof(AllocBlock)*(block_count+1));
+      if(!blocks)
+        return 0;
+      AllocBlock *block = &blocks[block_count++];
+      block->pos = pos-curr_free;
+      block->size = size;
+      for(u32 i = block->pos; i < block->pos+size; i+=8){
+        usage[i/32/8] |= 1<<(i%32);
+      }
+      // Unvirtualize the memory
+      memset(get_addr(block->pos),0xB00B5069,size);
+      return block->pos;
+    }
+  }
+  if(alloc_extend(size))
+    return 0;
+
+  // Try again after extending the buffer
+  return flisp_alloc(size); 
+}
+
+// TODO : make it efficient
+u32 flisp_realloc(u32 pos, u32 size){
+  if(!pos)
+    return flisp_alloc(size);
+  u32 new = flisp_alloc(size);
+  if(!new)
+   return 0;
+  AllocBlock *block = get_block(pos);
+  memcpy(get_addr(new),get_addr(pos),block->size);
+  flisp_free(pos);
+  return new; 
+}
+
+void flisp_free(u32 pos){
+  AllocBlock *ret = get_block(pos);
   if(!ret)
     return;
   i32 bpos = (size_t)(ret-blocks)/sizeof(AllocBlock);
diff --git a/src/exec_common.h b/src/exec_common.h
index fe63d65..f3b35bb 100644
--- a/src/exec_common.h
+++ b/src/exec_common.h
@@ -27,17 +27,21 @@ void runtime_err(char *s);
 
 int evaluate(Value val);
 
+
 int alloc_init();
 
-// All internal allocator memory is guaranteed to be free range and 32bit
-u32 flisp_alloc(size_t size);
+void alloc_clean();
+
+// All internal allocator memory is guaranteed to be free range
+u32 flisp_alloc(u32 size);
+
+u32 flisp_realloc(u32 pos, u32 size);
 
 void flisp_free(u32 pos);
 
-void *flisp_realloc(u32 pos, size_t size);
-
 void *get_addr(u32 pos);
 
+
 Value is(Tag tag, Value b);
 
 Value cast(Tag tag, Value b);
diff --git a/src/parser.y b/src/parser.y
index fc0be05..2fb6ba2 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -144,8 +144,6 @@ void yyerror(char *s){
 extern FILE *yyin;
 
 int main(int argc, char *argv[]){
-  alloc_init();
-
   i32 fpos = 1;
  
   if(argc > 1){ 
@@ -167,6 +165,8 @@ int main(int argc, char *argv[]){
     yyin = stdin;
   }
 
+  alloc_init();
+
   make_stack();
   yyparse();
   free_stack();
diff --git a/src/tests.c b/src/tests.c
index 8d8e438..a72b484 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -19,12 +19,14 @@
 
 #include <assert.h>
 #include <stdio.h>
+#include <string.h>
 #include <stdlib.h>
 
 #include "types.h"
 #include "parser.h"
 #include "code_defs.h"
 #include "byte_defs.h"
+#include "exec_common.h"
 
 typedef int (test_fun_t)(void);
 
@@ -66,6 +68,50 @@ int t_free_hashmap(){
   return 0;
 }
 
+int t_alloc_init(){
+  return alloc_init(); 
+}
+
+int t_flisp_alloc(){
+  int err = 0;
+  u32 pos0 = flisp_alloc(sizeof(u64));
+  u32 pos1 = flisp_alloc(sizeof(u64));
+  err += !pos0 || !pos1;
+  if(err)
+    return 1;
+  err += pos0 == pos1;
+  u64 *ptr0 = get_addr(pos0);
+  u64 *ptr1 = get_addr(pos1);
+  *ptr1 = 0;
+  *ptr0 = 0xFFFFFFFFFFFFFFFF;
+  err += !!*ptr1;
+  flisp_free(pos0);
+  flisp_free(pos1);
+
+  return err;
+}
+
+int t_flisp_realloc(){
+  int err = 0;
+  u8 ref[10] = {1,2,3,4,5,6,7,8,9,10};
+  u32 pos0 = flisp_alloc(5);
+  if(!pos0)
+    return 1;
+  u8 *ptr0 = get_addr(pos0);
+  memcpy(ptr0, ref, 5);
+  pos0 = flisp_realloc(pos0, 10);
+  if(!pos0)
+    return 1;
+  ptr0 = get_addr(pos0);
+  err += memcmp(ptr0, ref, 5);
+  return err;
+}
+
+int t_alloc_clean(){
+  alloc_clean();
+  return 0;
+}
+
 int t_get_type(){
   int err = 0;
   Tag ttag = get_type("int");
@@ -118,6 +164,10 @@ test_fun_t *tests[] = {
   t_hashmap_insert_get,
   t_hashmap_remove,
   t_free_hashmap,
+  t_alloc_init,
+  t_flisp_alloc,
+  t_flisp_realloc,
+  t_alloc_clean,
   t_get_type,
   t_make_stack,
   t_make_iconst,
@@ -132,6 +182,10 @@ char *names[] = {
   "hashmap_insert_get",
   "hashmap_remove",
   "free_hashmap",
+  "alloc_init",
+  "flisp_alloc",
+  "flisp_realloc",
+  "alloc_clean",
   "get_type",
   "make_stack",
   "make_iconst",