From 261a935dfa322ddcf8e9396099e6a4d8fca49ab5 Mon Sep 17 00:00:00 2001 From: SIGMazer Date: Sat, 8 Feb 2025 10:08:01 +0200 Subject: [PATCH 1/3] ci(memoryl_leaks): Fix CI valgrind check and resolve function memory leaks Signed-off-by: SIGMazer --- ast.c | 3 +++ run_valgrind_tests.sh | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ast.c b/ast.c index dcd6917..251b28a 100644 --- a/ast.c +++ b/ast.c @@ -3435,6 +3435,7 @@ void free_ast(ASTNode *node) case NODE_FUNCTION_DEF: SAFE_FREE(node->data.function_def.name); // Free parameters + free_parameters(node->data.function_def.parameters); if (node->data.function_def.body) { free_ast(node->data.function_def.body); @@ -3786,6 +3787,7 @@ void enter_function_scope(Function *func, ArgumentList *args) Variable *var = variable_new(curr_param->name); var->var_type = curr_param->type; add_variable_to_scope(curr_param->name, var); + SAFE_FREE(var); switch (curr_param->type) { @@ -3810,5 +3812,6 @@ void enter_function_scope(Function *func, ArgumentList *args) } curr_param = curr_param->next; } + reverse_parameter_list(&func->parameters); } diff --git a/run_valgrind_tests.sh b/run_valgrind_tests.sh index 9a08640..52e8a90 100755 --- a/run_valgrind_tests.sh +++ b/run_valgrind_tests.sh @@ -18,5 +18,9 @@ for f in test_cases/*.brainrot; do else valgrind --leak-check=full --error-exitcode=1 ./brainrot "$f" fi + if [[ $? -ne 0 ]]; then + echo "Valgrind failed on $f" + exit 1 + fi echo -done \ No newline at end of file +done From d7c491cae3613bd1e39955e26ca49b28999cbb16 Mon Sep 17 00:00:00 2001 From: SIGMazer Date: Sat, 8 Feb 2025 18:21:51 +0200 Subject: [PATCH 2/3] feat(memory): Regoin based allocation Signed-off-by: SIGMazer --- Makefile | 2 +- ast.c | 384 ++++++++++++++++++++++++++-------------------------- ast.h | 10 +- lang.l | 1 + lang.y | 2 +- lib/arena.c | 123 +++++++++++++++++ lib/arena.h | 26 ++++ 7 files changed, 352 insertions(+), 196 deletions(-) create mode 100644 lib/arena.c create mode 100644 lib/arena.h diff --git a/Makefile b/Makefile index 88cbded..efd003d 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ LDFLAGS := -lfl -lm # Source files and directories SRC_DIR := lib DEBUG_FLAGS := -g -SRCS := $(SRC_DIR)/hm.c $(SRC_DIR)/mem.c $(SRC_DIR)/input.c ast.c +SRCS := $(SRC_DIR)/hm.c $(SRC_DIR)/mem.c $(SRC_DIR)/input.c $(SRC_DIR)/arena.c ast.c GENERATED_SRCS := lang.tab.c lex.yy.c ALL_SRCS := $(SRCS) $(GENERATED_SRCS) diff --git a/ast.c b/ast.c index 251b28a..06c11ef 100644 --- a/ast.c +++ b/ast.c @@ -2,7 +2,6 @@ #include "ast.h" #include "lib/mem.h" -#include "lib/hm.h" #include #include #include @@ -15,6 +14,7 @@ JumpBuffer *jump_buffer = {0}; Function *function_table = NULL; jmp_buf return_jump_buf; ReturnValue current_return_value; +Arena arena; TypeModifiers current_modifiers = {false, false, false, false, false}; extern VarType current_var_type; @@ -239,7 +239,7 @@ void execute_switch_statement(ASTNode *node) static ASTNode *create_node(NodeType type, VarType var_type, TypeModifiers modifiers) { - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); if (!node) { yyerror("Error: Memory allocation failed for ASTNode.\n"); @@ -262,7 +262,7 @@ ASTNode *create_int_node(int value) ASTNode *create_array_declaration_node(char *name, int length, VarType var_type) { - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); if (!node) return NULL; @@ -270,13 +270,13 @@ ASTNode *create_array_declaration_node(char *name, int length, VarType var_type) node->var_type = var_type; node->is_array = true; node->array_length = length; - node->data.array.name = safe_strdup(name); + node->data.array.name = ARENA_STRDUP(name); return node; } ASTNode *create_array_access_node(char *name, ASTNode *index) { - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); if (!node) { yyerror("Memory allocation failed"); @@ -284,7 +284,7 @@ ASTNode *create_array_access_node(char *name, ASTNode *index) } node->type = NODE_ARRAY_ACCESS; - node->data.array.name = safe_strdup(name); + node->data.array.name = ARENA_STRDUP(name); node->data.array.index = index; node->is_array = true; @@ -1795,7 +1795,7 @@ bool evaluate_expression_bool(ASTNode *node) ArgumentList *create_argument_list(ASTNode *expr, ArgumentList *existing_list) { - ArgumentList *new_node = SAFE_MALLOC(ArgumentList); + ArgumentList *new_node = ARENA_ALLOC(ArgumentList); new_node->expr = expr; new_node->next = NULL; @@ -1818,7 +1818,7 @@ ArgumentList *create_argument_list(ASTNode *expr, ArgumentList *existing_list) ASTNode *create_print_statement_node(ASTNode *expr) { - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); node->type = NODE_PRINT_STATEMENT; node->data.op.left = expr; return node; @@ -1826,7 +1826,7 @@ ASTNode *create_print_statement_node(ASTNode *expr) ASTNode *create_error_statement_node(ASTNode *expr) { - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); node->type = NODE_ERROR_STATEMENT; node->data.op.left = expr; return node; @@ -1837,14 +1837,14 @@ ASTNode *create_statement_list(ASTNode *statement, ASTNode *existing_list) if (!existing_list) { // If there's no existing list, create a new one - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); if (!node) { yyerror("Memory allocation failed"); return NULL; } node->type = NODE_STATEMENT_LIST; - node->data.statements = SAFE_MALLOC(StatementList); + node->data.statements = ARENA_ALLOC(StatementList); if (!node->data.statements) { SAFE_FREE(node); @@ -1864,7 +1864,7 @@ ASTNode *create_statement_list(ASTNode *statement, ASTNode *existing_list) sl = sl->next; } // Now sl is the last element; append the new statement - StatementList *new_item = SAFE_MALLOC(StatementList); + StatementList *new_item = ARENA_ALLOC(StatementList); if (!new_item) { yyerror("Memory allocation failed"); @@ -2527,7 +2527,7 @@ void execute_do_while_statement(ASTNode *node) ASTNode *create_if_statement_node(ASTNode *condition, ASTNode *then_branch, ASTNode *else_branch) { - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); node->type = NODE_IF_STATEMENT; node->data.if_stmt.condition = condition; node->data.if_stmt.then_branch = then_branch; @@ -2537,15 +2537,15 @@ ASTNode *create_if_statement_node(ASTNode *condition, ASTNode *then_branch, ASTN ASTNode *create_string_literal_node(char *string) { - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); node->type = NODE_STRING_LITERAL; - node->data.name = safe_strdup(string); + node->data.name = ARENA_STRDUP(string); return node; } ASTNode *create_switch_statement_node(ASTNode *expression, CaseNode *cases) { - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); node->type = NODE_SWITCH_STATEMENT; node->data.switch_stmt.expression = expression; node->data.switch_stmt.cases = cases; @@ -2554,7 +2554,7 @@ ASTNode *create_switch_statement_node(ASTNode *expression, CaseNode *cases) CaseNode *create_case_node(ASTNode *value, ASTNode *statements) { - CaseNode *node = SAFE_MALLOC(CaseNode); + CaseNode *node = ARENA_ALLOC(CaseNode); node->value = value; node->statements = statements; node->next = NULL; @@ -2579,7 +2579,7 @@ CaseNode *append_case_list(CaseNode *list, CaseNode *case_node) ASTNode *create_break_node() { - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); node->type = NODE_BREAK_STATEMENT; node->data.break_stmt = NULL; return node; @@ -3117,7 +3117,7 @@ void *evaluate_array_access(ASTNode *node) } // Allocate and return value based on type - void *result = SAFE_MALLOC(double); // Use largest possible type + void *result = ARENA_ALLOC(double); // Use largest possible type switch (var->var_type) { case VAR_FLOAT: @@ -3259,8 +3259,6 @@ void populate_array_variable(char *name, ExpressionList *list) yyerror("Unsupported array type"); return; } - - SAFE_FREE(current->expr); current = current->next; if (current == list) break; @@ -3288,172 +3286,174 @@ void free_statement_list(StatementList *list) void free_ast(ASTNode *node) { - if (!node) - return; - - switch (node->type) - { - case NODE_IDENTIFIER: - SAFE_FREE(node->data.name); - break; - - case NODE_OPERATION: - case NODE_ASSIGNMENT: - case NODE_DECLARATION: - free_ast(node->data.op.left); - free_ast(node->data.op.right); - break; - - case NODE_UNARY_OPERATION: - free_ast(node->data.unary.operand); - break; - - case NODE_STATEMENT_LIST: - { - StatementList *current = node->data.statements; - while (current) - { - StatementList *next = current->next; - if (current->statement) - { - free_ast(current->statement); - } - SAFE_FREE(current); - current = next; - } - break; - } - - case NODE_SWITCH_STATEMENT: - if (node->data.switch_stmt.expression) - free_ast(node->data.switch_stmt.expression); - if (node->data.switch_stmt.cases) - { - CaseNode *current = node->data.switch_stmt.cases; - while (current) - { - CaseNode *next = current->next; - if (current->value) - free_ast(current->value); - if (current->statements) - free_ast(current->statements); - SAFE_FREE(current); - current = next; - } - } - break; - - case NODE_FOR_STATEMENT: - if (node->data.for_stmt.init) - free_ast(node->data.for_stmt.init); - if (node->data.for_stmt.cond) - free_ast(node->data.for_stmt.cond); - if (node->data.for_stmt.incr) - free_ast(node->data.for_stmt.incr); - if (node->data.for_stmt.body) - free_ast(node->data.for_stmt.body); - break; - - case NODE_WHILE_STATEMENT: - case NODE_DO_WHILE_STATEMENT: - if (node->data.while_stmt.cond) - free_ast(node->data.while_stmt.cond); - if (node->data.while_stmt.body) - free_ast(node->data.while_stmt.body); - break; - - case NODE_ARRAY_ACCESS: - if (node->data.array.name) - { - SAFE_FREE(node->data.array.name); - } - if (node->data.array.index) - { - free_ast(node->data.array.index); - } - break; - - case NODE_IF_STATEMENT: - if (node->data.if_stmt.condition) - free_ast(node->data.if_stmt.condition); - if (node->data.if_stmt.then_branch) - free_ast(node->data.if_stmt.then_branch); - if (node->data.if_stmt.else_branch) - free_ast(node->data.if_stmt.else_branch); - break; - - case NODE_SIZEOF: - if (node->data.sizeof_stmt.expr) - free_ast(node->data.sizeof_stmt.expr); - break; - - case NODE_BREAK_STATEMENT: - // Nothing additional to free - break; - - case NODE_FUNC_CALL: - if (node->data.func_call.function_name) - { - SAFE_FREE(node->data.func_call.function_name); - } - ArgumentList *current_arg = node->data.func_call.arguments; - while (current_arg) - { - ArgumentList *next_arg = current_arg->next; - if (current_arg->expr) - { - free_ast(current_arg->expr); - } - SAFE_FREE(current_arg); - current_arg = next_arg; - } - break; - - case NODE_STRING_LITERAL: - if (node->data.name) - { - SAFE_FREE(node->data.name); - } - break; - - case NODE_INT: - case NODE_SHORT: - case NODE_FLOAT: - case NODE_DOUBLE: - case NODE_BOOLEAN: - case NODE_CHAR: - // These nodes don't have additional allocations - break; - - case NODE_ERROR_STATEMENT: - case NODE_PRINT_STATEMENT: - if (node->data.op.left) - { - free_ast(node->data.op.left); - } - break; - case NODE_FUNCTION_DEF: - SAFE_FREE(node->data.function_def.name); - // Free parameters - free_parameters(node->data.function_def.parameters); - if (node->data.function_def.body) - { - free_ast(node->data.function_def.body); - } - break; - case NODE_RETURN: - if (node->data.op.left) - { - free_ast(node->data.op.left); - } - break; - default: - fprintf(stderr, "Warning: Unknown node type in free_ast: %d\n", node->type); - break; - } - - // Free the node itself - SAFE_FREE(node); + (void)node; + arena_free(&arena); + // if (!node) + // return; + // + // switch (node->type) + // { + // case NODE_IDENTIFIER: + // SAFE_FREE(node->data.name); + // break; + // + // case NODE_OPERATION: + // case NODE_ASSIGNMENT: + // case NODE_DECLARATION: + // free_ast(node->data.op.left); + // free_ast(node->data.op.right); + // break; + // + // case NODE_UNARY_OPERATION: + // free_ast(node->data.unary.operand); + // break; + // + // case NODE_STATEMENT_LIST: + // { + // StatementList *current = node->data.statements; + // while (current) + // { + // StatementList *next = current->next; + // if (current->statement) + // { + // free_ast(current->statement); + // } + // SAFE_FREE(current); + // current = next; + // } + // break; + // } + // + // case NODE_SWITCH_STATEMENT: + // if (node->data.switch_stmt.expression) + // free_ast(node->data.switch_stmt.expression); + // if (node->data.switch_stmt.cases) + // { + // CaseNode *current = node->data.switch_stmt.cases; + // while (current) + // { + // CaseNode *next = current->next; + // if (current->value) + // free_ast(current->value); + // if (current->statements) + // free_ast(current->statements); + // SAFE_FREE(current); + // current = next; + // } + // } + // break; + // + // case NODE_FOR_STATEMENT: + // if (node->data.for_stmt.init) + // free_ast(node->data.for_stmt.init); + // if (node->data.for_stmt.cond) + // free_ast(node->data.for_stmt.cond); + // if (node->data.for_stmt.incr) + // free_ast(node->data.for_stmt.incr); + // if (node->data.for_stmt.body) + // free_ast(node->data.for_stmt.body); + // break; + // + // case NODE_WHILE_STATEMENT: + // case NODE_DO_WHILE_STATEMENT: + // if (node->data.while_stmt.cond) + // free_ast(node->data.while_stmt.cond); + // if (node->data.while_stmt.body) + // free_ast(node->data.while_stmt.body); + // break; + // + // case NODE_ARRAY_ACCESS: + // if (node->data.array.name) + // { + // SAFE_FREE(node->data.array.name); + // } + // if (node->data.array.index) + // { + // free_ast(node->data.array.index); + // } + // break; + // + // case NODE_IF_STATEMENT: + // if (node->data.if_stmt.condition) + // free_ast(node->data.if_stmt.condition); + // if (node->data.if_stmt.then_branch) + // free_ast(node->data.if_stmt.then_branch); + // if (node->data.if_stmt.else_branch) + // free_ast(node->data.if_stmt.else_branch); + // break; + // + // case NODE_SIZEOF: + // if (node->data.sizeof_stmt.expr) + // free_ast(node->data.sizeof_stmt.expr); + // break; + // + // case NODE_BREAK_STATEMENT: + // // Nothing additional to free + // break; + // + // case NODE_FUNC_CALL: + // if (node->data.func_call.function_name) + // { + // SAFE_FREE(node->data.func_call.function_name); + // } + // ArgumentList *current_arg = node->data.func_call.arguments; + // while (current_arg) + // { + // ArgumentList *next_arg = current_arg->next; + // if (current_arg->expr) + // { + // free_ast(current_arg->expr); + // } + // SAFE_FREE(current_arg); + // current_arg = next_arg; + // } + // break; + // + // case NODE_STRING_LITERAL: + // if (node->data.name) + // { + // SAFE_FREE(node->data.name); + // } + // break; + // + // case NODE_INT: + // case NODE_SHORT: + // case NODE_FLOAT: + // case NODE_DOUBLE: + // case NODE_BOOLEAN: + // case NODE_CHAR: + // // These nodes don't have additional allocations + // break; + // + // case NODE_ERROR_STATEMENT: + // case NODE_PRINT_STATEMENT: + // if (node->data.op.left) + // { + // free_ast(node->data.op.left); + // } + // break; + // case NODE_FUNCTION_DEF: + // SAFE_FREE(node->data.function_def.name); + // // Free parameters + // free_parameters(node->data.function_def.parameters); + // if (node->data.function_def.body) + // { + // free_ast(node->data.function_def.body); + // } + // break; + // case NODE_RETURN: + // if (node->data.op.left) + // { + // free_ast(node->data.op.left); + // } + // break; + // default: + // fprintf(stderr, "Warning: Unknown node type in free_ast: %d\n", node->type); + // break; + // } + // + // // Free the node itself + // SAFE_FREE(node); } Scope *create_scope(Scope *parent) @@ -3547,7 +3547,7 @@ void add_variable_to_scope(const char *name, Variable *var) ASTNode *create_return_node(ASTNode *expr) { - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); if (!node) { yyerror("Memory allocation failed"); @@ -3649,14 +3649,14 @@ void handle_return_statement(ASTNode *expr) Parameter *create_parameter(char *name, VarType type, Parameter *next) { - Parameter *param = SAFE_MALLOC(Parameter); + Parameter *param = ARENA_ALLOC(Parameter); if (!param) { yyerror("Failed to allocate memory for parameter"); return NULL; } - param->name = safe_strdup(name); + param->name = ARENA_STRDUP(name); param->type = type; param->next = next; @@ -3665,7 +3665,7 @@ Parameter *create_parameter(char *name, VarType type, Parameter *next) ASTNode *create_function_def_node(char *name, VarType return_type, Parameter *params, ASTNode *body) { - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); if (!node) { yyerror("Failed to allocate memory for function definition node"); @@ -3673,7 +3673,7 @@ ASTNode *create_function_def_node(char *name, VarType return_type, Parameter *pa } node->type = NODE_FUNCTION_DEF; - node->data.function_def.name = safe_strdup(name); + node->data.function_def.name = ARENA_STRDUP(name); node->data.function_def.return_type = return_type; node->data.function_def.parameters = params; node->data.function_def.body = body; diff --git a/ast.h b/ast.h index 3d62572..f1328d9 100644 --- a/ast.h +++ b/ast.h @@ -4,6 +4,7 @@ #define AST_H #include "lib/hm.h" +#include "lib/arena.h" #include "lib/mem.h" #include #include @@ -390,13 +391,18 @@ void free_function_table(void); extern TypeModifiers current_modifiers; +extern Arena arena; + +#define ARENA_ALLOC(type) arena_alloc(&arena, sizeof(type)) +#define ARENA_STRDUP(str) arena_strdup(&arena, str) + /* Macros for assigning specific fields to a node */ #define SET_DATA_INT(node, value) ((node)->data.ivalue = (value)) #define SET_DATA_SHORT(node, value) ((node)->data.svalue = (value)) #define SET_DATA_FLOAT(node, value) ((node)->data.fvalue = (value)) #define SET_DATA_DOUBLE(node, value) ((node)->data.dvalue = (value)) #define SET_DATA_BOOL(node, value) ((node)->data.bvalue = (value) ? 1 : 0) -#define SET_DATA_NAME(node, n) ((node)->data.name = safe_strdup(n)) +#define SET_DATA_NAME(node, n) ((node)->data.name = ARENA_STRDUP(n)) #define SET_SIZEOF(node, n) ((node)->data.sizeof_stmt.expr = (n)) #define SET_DATA_OP(node, l, r, opr) \ do \ @@ -432,7 +438,7 @@ extern TypeModifiers current_modifiers; #define SET_DATA_FUNC_CALL(node, func_name, args) \ do \ { \ - (node)->data.func_call.function_name = safe_strdup(func_name); \ + (node)->data.func_call.function_name = ARENA_STRDUP(func_name); \ (node)->data.func_call.arguments = (args); \ } while (0) diff --git a/lang.l b/lang.l index a49b9b5..c3db194 100644 --- a/lang.l +++ b/lang.l @@ -4,6 +4,7 @@ #include #include "ast.h" #include "lib/mem.h" +#include "lib/arena.h" #include "lang.tab.h" VarType current_var_type = NONE; diff --git a/lang.y b/lang.y index 1838994..19b5df0 100644 --- a/lang.y +++ b/lang.y @@ -434,7 +434,7 @@ assignment: | IDENTIFIER LBRACKET expression RBRACKET EQUALS expression { ASTNode *access = create_array_access_node($1, $3); - ASTNode *node = SAFE_MALLOC(ASTNode); + ASTNode *node = ARENA_ALLOC(ASTNode); if (!node) { yyerror("Memory allocation failed"); SAFE_FREE($1); diff --git a/lib/arena.c b/lib/arena.c new file mode 100644 index 0000000..d496741 --- /dev/null +++ b/lib/arena.c @@ -0,0 +1,123 @@ +#include "arena.h" + +/* + * @brref Create a new arena with a given size. + * @param size The size of the arena. + * @return The new arena. + */ +Region *region_new(size_t size) +{ + size_t total_size = sizeof(Region) + sizeof(uintptr_t) * size; + Region *region = (Region *)malloc(total_size); + region->capacity = size; + region->count = 0; + region->next = NULL; + return region; +} + +/* + * @brref free the region. + * @param region The region to free. + */ +void region_free(Region *region) +{ + free(region); +} + +/* + * @brief allocate memory from the arena. + * @param arena The arena to allocate from. + * @param size_bytes The size of the memory to allocate. + * @return The pointer to the allocated memory. + */ +void *arena_alloc(Arena *arena, size_t size_bytes) +{ + if(arena == NULL) + { + arena = (Arena*)malloc(sizeof(struct Arena)); + arena->start = NULL; + arena->end = NULL; + } + size_t size = (size_bytes + sizeof(uintptr_t) - 1)/sizeof(uintptr_t); + if (arena->end == NULL) + { + assert(arena->start == NULL); + size_t capacity = DEFAULT_REGION_SIZE; + if (size > capacity) capacity = size; + arena->end = region_new(capacity); + arena->start = arena->end; + } + + while (arena->end->count + size > arena->end->capacity && arena->end->next != NULL) + { + arena->end = arena->end->next; + } + + if (arena->end->count + size > arena->end->capacity) + { + assert(arena->end->next == NULL); + size_t cap = DEFAULT_REGION_SIZE; + if (size > cap) cap = size; + arena->end->next = region_new(cap); + arena->end = arena->end->next; + } + + void *result = &arena->end->data[arena->end->count]; + arena->end->count += size; + return result; +} + + +/* + * @brief make a copy of a string in the arena. + * @param arena The arena to allocate from. + * @param str The string to copy. + * @return The pointer to the copied string. + */ +char *arena_strdup(Arena *arena, const char *str) +{ + size_t len = strlen(str); + char *result = (char *)arena_alloc(arena, len + 1); + memcpy(result, str, len); + result[len] = '\0'; + return result; +} + +/* + * @brief reset the arena. + * @param arena The arena to reset. + */ + +void arena_reset(Arena *arena) +{ + arena->end = arena->start; + while (arena->end->next != NULL) + { + Region *next = arena->end->next; + region_free(arena->end); + arena->end = next; + } + arena->end->count = 0; +} + +/* + * @brief free the arena. + * @param arena The arena to free. + */ +void arena_free(Arena *arena) +{ + if (arena == NULL) return; // Prevent NULL pointer dereference + + Region *current = arena->start; + while (current != NULL) + { + Region *next = current->next; + region_free(current); + current = next; + } + + // Clear the arena structure + arena->start = NULL; + arena->end = NULL; +} + diff --git a/lib/arena.h b/lib/arena.h new file mode 100644 index 0000000..a62636a --- /dev/null +++ b/lib/arena.h @@ -0,0 +1,26 @@ +#ifndef AREANA_H +#define AREANA_H + +#include "mem.h" + +// Default region size 4KB or 1 page of memory +#define DEFAULT_REGION_SIZE (4 * 1024) + +typedef struct Region { + struct Region *next; + size_t count; + size_t capacity; + uintptr_t data[]; +} Region; + +typedef struct Arena { + Region *start, *end; +} Arena; + +Region *region_new(size_t size); +void region_free(Region *region); +void *arena_alloc(Arena *arena, size_t size_bytes); +char *arena_strdup(Arena *arena, const char *str); +void arena_reset(Arena *arena); +void arena_free(Arena *arena); +#endif // AREANA_H From 3a9abce3047cca90cd165c0be37beab27d7f2e4d Mon Sep 17 00:00:00 2001 From: SIGMazer Date: Sat, 8 Feb 2025 18:48:06 +0200 Subject: [PATCH 3/3] remove dead code Signed-off-by: SIGMazer --- ast.c | 183 +-------------------------------------------------------- ast.h | 4 +- lang.y | 4 +- 3 files changed, 4 insertions(+), 187 deletions(-) diff --git a/ast.c b/ast.c index 06c11ef..e952d1c 100644 --- a/ast.c +++ b/ast.c @@ -2113,14 +2113,11 @@ void execute_assignment(ASTNode *node) break; default: yyerror("Unsupported array type"); - free_ast(node); return; } - free_ast(node); return; } yyerror("Undefined array variable"); - free_ast(node); return; } @@ -2140,7 +2137,6 @@ void execute_assignment(ASTNode *node) { yyerror("Failed to set integer variable"); } - free_ast(node); return; } } @@ -3284,176 +3280,9 @@ void free_statement_list(StatementList *list) } } -void free_ast(ASTNode *node) +void free_ast() { - (void)node; arena_free(&arena); - // if (!node) - // return; - // - // switch (node->type) - // { - // case NODE_IDENTIFIER: - // SAFE_FREE(node->data.name); - // break; - // - // case NODE_OPERATION: - // case NODE_ASSIGNMENT: - // case NODE_DECLARATION: - // free_ast(node->data.op.left); - // free_ast(node->data.op.right); - // break; - // - // case NODE_UNARY_OPERATION: - // free_ast(node->data.unary.operand); - // break; - // - // case NODE_STATEMENT_LIST: - // { - // StatementList *current = node->data.statements; - // while (current) - // { - // StatementList *next = current->next; - // if (current->statement) - // { - // free_ast(current->statement); - // } - // SAFE_FREE(current); - // current = next; - // } - // break; - // } - // - // case NODE_SWITCH_STATEMENT: - // if (node->data.switch_stmt.expression) - // free_ast(node->data.switch_stmt.expression); - // if (node->data.switch_stmt.cases) - // { - // CaseNode *current = node->data.switch_stmt.cases; - // while (current) - // { - // CaseNode *next = current->next; - // if (current->value) - // free_ast(current->value); - // if (current->statements) - // free_ast(current->statements); - // SAFE_FREE(current); - // current = next; - // } - // } - // break; - // - // case NODE_FOR_STATEMENT: - // if (node->data.for_stmt.init) - // free_ast(node->data.for_stmt.init); - // if (node->data.for_stmt.cond) - // free_ast(node->data.for_stmt.cond); - // if (node->data.for_stmt.incr) - // free_ast(node->data.for_stmt.incr); - // if (node->data.for_stmt.body) - // free_ast(node->data.for_stmt.body); - // break; - // - // case NODE_WHILE_STATEMENT: - // case NODE_DO_WHILE_STATEMENT: - // if (node->data.while_stmt.cond) - // free_ast(node->data.while_stmt.cond); - // if (node->data.while_stmt.body) - // free_ast(node->data.while_stmt.body); - // break; - // - // case NODE_ARRAY_ACCESS: - // if (node->data.array.name) - // { - // SAFE_FREE(node->data.array.name); - // } - // if (node->data.array.index) - // { - // free_ast(node->data.array.index); - // } - // break; - // - // case NODE_IF_STATEMENT: - // if (node->data.if_stmt.condition) - // free_ast(node->data.if_stmt.condition); - // if (node->data.if_stmt.then_branch) - // free_ast(node->data.if_stmt.then_branch); - // if (node->data.if_stmt.else_branch) - // free_ast(node->data.if_stmt.else_branch); - // break; - // - // case NODE_SIZEOF: - // if (node->data.sizeof_stmt.expr) - // free_ast(node->data.sizeof_stmt.expr); - // break; - // - // case NODE_BREAK_STATEMENT: - // // Nothing additional to free - // break; - // - // case NODE_FUNC_CALL: - // if (node->data.func_call.function_name) - // { - // SAFE_FREE(node->data.func_call.function_name); - // } - // ArgumentList *current_arg = node->data.func_call.arguments; - // while (current_arg) - // { - // ArgumentList *next_arg = current_arg->next; - // if (current_arg->expr) - // { - // free_ast(current_arg->expr); - // } - // SAFE_FREE(current_arg); - // current_arg = next_arg; - // } - // break; - // - // case NODE_STRING_LITERAL: - // if (node->data.name) - // { - // SAFE_FREE(node->data.name); - // } - // break; - // - // case NODE_INT: - // case NODE_SHORT: - // case NODE_FLOAT: - // case NODE_DOUBLE: - // case NODE_BOOLEAN: - // case NODE_CHAR: - // // These nodes don't have additional allocations - // break; - // - // case NODE_ERROR_STATEMENT: - // case NODE_PRINT_STATEMENT: - // if (node->data.op.left) - // { - // free_ast(node->data.op.left); - // } - // break; - // case NODE_FUNCTION_DEF: - // SAFE_FREE(node->data.function_def.name); - // // Free parameters - // free_parameters(node->data.function_def.parameters); - // if (node->data.function_def.body) - // { - // free_ast(node->data.function_def.body); - // } - // break; - // case NODE_RETURN: - // if (node->data.op.left) - // { - // free_ast(node->data.op.left); - // } - // break; - // default: - // fprintf(stderr, "Warning: Unknown node type in free_ast: %d\n", node->type); - // break; - // } - // - // // Free the node itself - // SAFE_FREE(node); } Scope *create_scope(Scope *parent) @@ -3684,16 +3513,6 @@ ASTNode *create_function_def_node(char *name, VarType return_type, Parameter *pa return node; } -void free_parameters(Parameter *param) -{ - while (param) - { - Parameter *next = param->next; - SAFE_FREE(param->name); - SAFE_FREE(param); - param = next; - } -} void free_function_table(void) { diff --git a/ast.h b/ast.h index f1328d9..73dbd6e 100644 --- a/ast.h +++ b/ast.h @@ -343,7 +343,7 @@ ExpressionList *create_expression_list(ASTNode *expr); ExpressionList *append_expression_list(ExpressionList *list, ASTNode *expr); void free_expression_list(ExpressionList *list); void populate_array_variable(char *name, ExpressionList *list); -void free_ast(ASTNode *node); +void free_ast(void); /* Evaluation and execution functions */ void *evaluate_array_access(ASTNode *node); @@ -370,7 +370,6 @@ void execute_baka_call(ArgumentList *args); void execute_ragequit_call(ArgumentList *args); void execute_chill_call(ArgumentList *args); void execute_slorp_call(ArgumentList *args); -void free_ast(ASTNode *node); void reset_modifiers(void); bool check_and_mark_identifier(ASTNode *node, const char *contextErrorMessage); void bruh(); @@ -386,7 +385,6 @@ void execute_function_call(const char *name, ArgumentList *args); ASTNode *create_function_def_node(char *name, VarType return_type, Parameter *params, ASTNode *body); void handle_return_statement(ASTNode *expr); void *handle_binary_operation(ASTNode *node); -void free_parameters(Parameter *param); void free_function_table(void); extern TypeModifiers current_modifiers; diff --git a/lang.y b/lang.y index 19b5df0..3726cbc 100644 --- a/lang.y +++ b/lang.y @@ -513,7 +513,7 @@ int main(int argc, char *argv[]) { } fclose(source); - free_ast(root); + free_ast(); free_function_table(); free_scope(current_scope); yylex_destroy(); @@ -701,7 +701,7 @@ double slorp_double(double var) { void cleanup() { // Free the AST - free_ast(root); + free_ast(); // Free the scope free_scope(current_scope);