From d54125daa6d1f42dc844ba425c122ba2d739235c Mon Sep 17 00:00:00 2001 From: Bram van den Heuvel Date: Fri, 21 Feb 2025 16:47:33 +0100 Subject: [PATCH] Refactor BlockHeader type on heap --- low.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 15 deletions(-) diff --git a/low.c b/low.c index 1c25ac5..6328778 100644 --- a/low.c +++ b/low.c @@ -11,7 +11,11 @@ typedef struct Text Text; typedef struct UnionType UnionType; typedef struct Var Var; -#define MEM_SIZE 200//1024 * 1024 // 1 MB +// You can change this number to decide how much memory the program is allowed +// 0 - 193 bytes -> The program refuses to start +// 194 - 217 bytes -> The program starts but doesn't do anything +// 218 + bytes -> The program runs successfully +#define MEM_SIZE 193 //1024 * 1024 // 1 MB #define EXIT_GRACEFULLY 0 #define EXIT_MEMORY_LIMIT_TOO_LOW 11 @@ -38,11 +42,20 @@ typedef struct Var Var; // Memory block structure // This block functions as a header for memory allocations on the heap typedef struct BlockHeader { - size_t size; int free; struct BlockHeader *next; } BlockHeader; +#define BLOCK_SIZE(header) ({ \ + size_t s; \ + if (header->next) { \ + s = (uint8_t *)(header->next) - (uint8_t *)header; \ + } else { \ + s = (uint8_t *)(stack_top) - (uint8_t *)header; \ + } \ + s - sizeof(BlockHeader); \ +}) + // Global memory pool static uint8_t *memory = NULL; static uintptr_t heap_base; @@ -69,7 +82,6 @@ void init_memory() { BlockHeader *curr = (BlockHeader *)heap_base; curr->free = 1; - curr->size = MEM_SIZE - sizeof(BlockHeader); curr->next = NULL; } @@ -78,17 +90,19 @@ void init_memory() { void *ptr = NULL; \ BlockHeader *curr = (BlockHeader *)heap_base; \ while(curr) { \ - if (curr->free && curr->size >= (nbytes)) { \ + size_t size = (BLOCK_SIZE(curr)); \ + if (curr->free && size >= (nbytes)) { \ /* If there's enough memory left over, split off into two */ \ - if (curr->size >= (nbytes) + sizeof(BlockHeader) + 1) { \ + if (size >= (nbytes) + sizeof(BlockHeader) + 1) { \ BlockHeader *new_block = (BlockHeader *)( \ (uint8_t *)curr + sizeof(BlockHeader) + (nbytes) \ ); \ - new_block->size = curr->size - (nbytes) - sizeof(BlockHeader); \ new_block->free = 1; \ new_block->next = curr->next; \ - curr->size = (nbytes); \ curr->next = new_block; \ + if ((uint8_t *)heap_top < (uint8_t *)new_block) { \ + heap_top = (uintptr_t)new_block + sizeof(BlockHeader); \ + } \ } \ /* Assign block to new memory */ \ curr->free = 0; \ @@ -123,26 +137,27 @@ void init_memory() { // Pointer for debugging: print the heap to stdout #define HEAP_PRINT_WIDTH 60 -#define HEAP_PRINT() ({ \ +#define HEAP_PRINT() ({ \ BlockHeader *curr = (BlockHeader *)heap_base; \ while (curr) { \ + size_t size = BLOCK_SIZE(curr); \ printf("BlockHeader at address %ld (physical %p): %lu byte", \ - (uint8_t *)curr - memory, curr, curr->size \ + (uint8_t *)curr - memory, curr, size \ ); \ - if (curr->size == 1) { printf(" of "); } else { printf("s of "); } \ + if (size == 1) { printf(" of "); } else { printf("s of "); } \ if (curr->free) { \ printf("free memory\n "); \ } else { \ printf("reserved memory\n "); \ } \ unsigned char *content = (uint8_t *)curr; \ - for (int i = 0; i < curr->size + sizeof(BlockHeader); i++) { \ + for (int i = 0; i < size + sizeof(BlockHeader); i++) { \ if (i == sizeof(BlockHeader)) { printf("| "); } \ printf("%02X ", content[i]); \ - if (i > HEAP_PRINT_WIDTH) { printf("..."); break; } \ + if (i > HEAP_PRINT_WIDTH) { printf("..."); break; } \ } \ printf("\n "); \ - for (int i = 0; i < curr->size + sizeof(BlockHeader); i++) { \ + for (int i = 0; i < size + sizeof(BlockHeader); i++) { \ if (i == sizeof(BlockHeader)) { printf("| "); } \ if (content[i] == 0) { printf(" "); \ } else if (content[i] >= 32 && content[i] < 127) { \ @@ -235,6 +250,43 @@ void init_memory() { stack_top += (nbytes); \ }) +#define MEM_DIAGNOSTICS(curr) ({ \ + printf("----------------------------\n"); \ + printf("Heap base at address %ld (physical %p)\n", \ + (uint8_t *)heap_base - (uint8_t *)memory, (uint8_t *)heap_base \ + ); \ + printf("Heap top at address %ld (physical %p)\n", \ + (uint8_t *)heap_top - (uint8_t *)memory, (uint8_t *)heap_top \ + ); \ + HEAP_PRINT(); \ + printf("----------------------------\n"); \ + printf("Heap base at address %ld (physical %p)\n", \ + (uint8_t *)heap_base - (uint8_t *)memory, (uint8_t *)heap_base \ + ); \ + printf("Heap top at address %ld (physical %p)\n", \ + (uint8_t *)heap_top - (uint8_t *)memory, (uint8_t *)heap_top \ + ); \ + printf("Stack top at address %ld (physical %p)\n", \ + (uint8_t *)stack_top - (uint8_t *)memory, (uint8_t *)stack_top \ + ); \ + printf("Stack base at address %ld (physical %p)\n", \ + (uint8_t *)stack_base - (uint8_t *)memory, (uint8_t *)stack_base \ + ); \ + printf("----------------------------\n"); \ + if (curr) { \ + STACK_PRINT(curr); \ + } else { \ + printf("Stack is NULL!\n"); \ + } \ + printf("Stack top at address %ld (physical %p)\n", \ + (uint8_t *)stack_top - (uint8_t *)memory, (uint8_t *)stack_top \ + ); \ + printf("Stack base at address %ld (physical %p)\n", \ + (uint8_t *)stack_base - (uint8_t *)memory, (uint8_t *)stack_base \ + ); \ + printf("----------------------------\n"); \ +}) + /* ============================================================================ * VARIABLES & VALUES @@ -376,10 +428,11 @@ int main(void) { var->value = v; curr->prevOut = var; curr->cont = fnsh; - + // STACK_PRINT(curr); - + while (curr) { + // MEM_DIAGNOSTICS(curr); switch (curr->code_id) { case CODE_F: { // f(x) = print(x) and return x