diff options
author | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2025-01-31 02:46:16 +0330 |
---|---|---|
committer | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2025-01-31 02:46:16 +0330 |
commit | 5a6f4613ab19a9c4bc9ead53da410d7ab9ff5837 (patch) | |
tree | 64053302ea59ac69fb830b3efad6a721cdd1e9b3 | |
parent | ce253ec2ae45879b331d9b9f77f786b78fbfcf2e (diff) |
make stuff more organized and safer
-rw-r--r-- | src/compiler/ast-tree.c | 16 | ||||
-rw-r--r-- | src/compiler/code-generator.c | 177 | ||||
-rw-r--r-- | src/compiler/code-generator.h | 32 | ||||
-rw-r--r-- | stdlib/main.asm | 11 |
4 files changed, 189 insertions, 47 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 097e45b..c9b719c 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -296,10 +296,10 @@ AstTree *copyAstTree(AstTree *tree) { case AST_TREE_TOKEN_TYPE_U64: return newAstTree(tree->token, NULL); case AST_TREE_TOKEN_VALUE_U64: - return newAstTree(AST_TREE_TOKEN_VALUE_U64, - (void *)(AstTreeU64)tree->metadata); + return newAstTree(tree->token, (void *)(AstTreeU64)tree->metadata); case AST_TREE_TOKEN_VARIABLE: - return newAstTree(AST_TREE_TOKEN_VARIABLE, tree->metadata); + return newAstTree(tree->token, tree->metadata); + case AST_TREE_TOKEN_OPERATOR_ASSIGN: case AST_TREE_TOKEN_FUNCTION: case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_TYPE_FUNCTION: @@ -869,6 +869,7 @@ bool hasTypeOf(AstTree *value, const AstTree *type) { case AST_TREE_TOKEN_VARIABLE: case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VARIABLE_DEFINE: + case AST_TREE_TOKEN_OPERATOR_ASSIGN: return false; case AST_TREE_TOKEN_NONE: } @@ -898,6 +899,7 @@ bool hasTypeOf(AstTree *value, const AstTree *type) { case AST_TREE_TOKEN_FUNCTION_CALL: case AST_TREE_TOKEN_VARIABLE: case AST_TREE_TOKEN_VARIABLE_DEFINE: + case AST_TREE_TOKEN_OPERATOR_ASSIGN: return false; case AST_TREE_TOKEN_NONE: } @@ -911,6 +913,7 @@ bool hasTypeOf(AstTree *value, const AstTree *type) { case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VARIABLE_DEFINE: + case AST_TREE_TOKEN_OPERATOR_ASSIGN: return false; case AST_TREE_TOKEN_NONE: } @@ -943,6 +946,7 @@ AstTreeFunction *getFunction(AstTree *value) { case AST_TREE_TOKEN_TYPE_U64: case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VARIABLE_DEFINE: + case AST_TREE_TOKEN_OPERATOR_ASSIGN: return NULL; case AST_TREE_TOKEN_NONE: } @@ -962,6 +966,7 @@ bool isConst(AstTree *value) { case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_FUNCTION_CALL: case AST_TREE_TOKEN_VARIABLE_DEFINE: + case AST_TREE_TOKEN_OPERATOR_ASSIGN: return false; case AST_TREE_TOKEN_VARIABLE: { AstTreeVariable *metadata = value->metadata; @@ -1009,6 +1014,7 @@ AstTree *makeTypeOf(AstTree *value) { } case AST_TREE_TOKEN_VARIABLE_DEFINE: case AST_TREE_TOKEN_KEYWORD_PRINT_U64: + case AST_TREE_TOKEN_OPERATOR_ASSIGN: case AST_TREE_TOKEN_NONE: } printLog("Bad token '%d'", value->token); @@ -1021,6 +1027,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) { case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VARIABLE_DEFINE: + case AST_TREE_TOKEN_OPERATOR_ASSIGN: return false; case AST_TREE_TOKEN_TYPE_TYPE: case AST_TREE_TOKEN_TYPE_VOID: @@ -1157,7 +1164,8 @@ bool setTypesFunctionCall(AstTree *tree) { } AstTreeFunction *function = getFunction(metadata->function); - if (function == NULL || function->arguments.size != metadata->parameters_size) { + if (function == NULL || + function->arguments.size != metadata->parameters_size) { printLog("Arguments doesn't match %ld != %ld", function->arguments.size, metadata->parameters_size); return false; diff --git a/src/compiler/code-generator.c b/src/compiler/code-generator.c index 24f0699..905f408 100644 --- a/src/compiler/code-generator.c +++ b/src/compiler/code-generator.c @@ -2,13 +2,18 @@ #include "compiler/ast-tree.h" #include "utils/log.h" #include "utils/memory.h" -#include "utils/string.h" #include <assert.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +void codeGeneratorOperandDestroy(CodeGeneratorOperand operand) { + if (operand.isReference) { + free(operand.value.reference); + } +} + void codeGeneratorDelete(CodeGeneratorCodes *code) { for (size_t i = 0; i < code->codes_size; ++i) { CodeGeneratorCode current = code->codes[i]; @@ -16,6 +21,7 @@ void codeGeneratorDelete(CodeGeneratorCodes *code) { case CODE_GENERATOR_INSTRUCTION_PRINT_U64: case CODE_GENERATOR_INSTRUCTION_DEF_VAR64: { CodeGeneratorOperand *metadata = current.metadata; + codeGeneratorOperandDestroy(*metadata); free(metadata); } case CODE_GENERATOR_INSTRUCTION_RET: @@ -25,34 +31,60 @@ void codeGeneratorDelete(CodeGeneratorCodes *code) { free(metadata); } continue; - case CODE_GENERATOR_INSTRUCTION_MOV_U64: { + case CODE_GENERATOR_INSTRUCTION_MOV_64: { CodeGeneratorDoubleOperand *metadata = current.metadata; - free(metadata->op0.value); - free(metadata->op1.value); + codeGeneratorOperandDestroy(metadata->op0); + codeGeneratorOperandDestroy(metadata->op1); free(metadata); } continue; } - printLog("Bad instruction %d", current.instruction); - exit(1); + UNREACHABLE; + } + for (size_t i = 0; i < code->defines_size; ++i) { + CodeGeneratorDefine current = code->defines[i]; + switch (current.type) { + case CODE_GENERATOR_TYPE_64: + codeGeneratorOperandDestroy(current.operand); + continue; + } + UNREACHABLE; } free(code->codes); free(code); } -CodeGeneratorOperand *newCodeGeneratorOperand(char *value, bool isReference) { +CodeGeneratorOperand *newCodeGeneratorOperand(void *value, bool isReference) { CodeGeneratorOperand *result = a404m_malloc(sizeof(*result)); - result->value = value; result->isReference = isReference; + if (isReference) { + result->value.reference = value; + } else { + result->value.value = (uint64_t)value; + } return result; } -CodeGeneratorOperand *makeCodeGeneratorOperand(AstTree tree) { +CodeGeneratorOperand makeCodeGeneratorOperand(void *value, bool isReference) { + CodeGeneratorOperand result = { + .isReference = isReference, + }; + + if (isReference) { + result.value.reference = value; + } else { + result.value.value = (uint64_t)value; + } + + return result; +} + +CodeGeneratorOperand *newCodeGeneratorOperandFromAstTree(AstTree tree) { switch (tree.token) { case AST_TREE_TOKEN_VALUE_U64: - return newCodeGeneratorOperand(u64ToString((AstTreeU64)tree.metadata), + return newCodeGeneratorOperand((void *)(uint64_t)(AstTreeU64)tree.metadata, false); case AST_TREE_TOKEN_VARIABLE: { AstTreeVariable *variable = tree.metadata; @@ -61,7 +93,7 @@ CodeGeneratorOperand *makeCodeGeneratorOperand(AstTree tree) { } if (variable->isConst) { return newCodeGeneratorOperand( - u64ToString((AstTreeU64)variable->value->metadata), false); + (void *)(uint64_t)(AstTreeU64)variable->value->metadata, false); } else { char *name = a404m_malloc( (variable->name_end - variable->name_begin + 1) * sizeof(*name)); @@ -98,6 +130,18 @@ CodeGeneratorCode createGenerateCode(char *label_begin, char *label_end, return code; } +CodeGeneratorDefine createGenerateDefine(char *label_begin, char *label_end, + CodeGeneratorOperand operand, + CodeGeneratorType type) { + CodeGeneratorDefine define = { + .label_begin = label_begin, + .label_end = label_end, + .operand = operand, + .type = type, + }; + return define; +} + CodeGeneratorCode *newGenerateCode(char *label_begin, char *label_end, CodeGeneratorInstruction instruction) { CodeGeneratorCode *result = a404m_malloc(sizeof(*result)); @@ -119,11 +163,26 @@ void generateCodePushCode(CodeGeneratorCodes *codes, CodeGeneratorCode code) { codes->codes_size += 1; } +void generateCodePushDefine(CodeGeneratorCodes *codes, + CodeGeneratorDefine define) { + size_t defines_size = + a404m_malloc_usable_size(codes->defines) / sizeof(*codes->defines); + if (defines_size == codes->defines_size) { + defines_size += defines_size / 2 + 1; + codes->defines = + a404m_realloc(codes->defines, defines_size * sizeof(*codes->defines)); + } + codes->defines[codes->defines_size] = define; + codes->defines_size += 1; +} + CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot) { CodeGeneratorCodes *codes = a404m_malloc(sizeof(*codes)); codes->codes = a404m_malloc(0); codes->codes_size = 0; + codes->defines = a404m_malloc(0); + codes->defines_size = 0; for (size_t i = 0; i < astTreeRoot->variables.size; ++i) { AstTreeVariable *variable = astTreeRoot->variables.data[i]; @@ -137,12 +196,12 @@ CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot) { continue; case AST_TREE_TOKEN_VALUE_U64: if (!variable->isConst) { - CodeGeneratorOperand *value = newCodeGeneratorOperand( - u64ToString((AstTreeU64)variable->value->metadata), false); - generateCodePushCode( - codes, - createGenerateCode(variable->name_begin, variable->name_end, - CODE_GENERATOR_INSTRUCTION_DEF_VAR64, value)); + CodeGeneratorOperand value = makeCodeGeneratorOperand( + (void *)(uint64_t)(AstTreeU64)variable->value->metadata, false); + generateCodePushDefine(codes, + createGenerateDefine(variable->name_begin, + variable->name_end, value, + CODE_GENERATOR_TYPE_64)); } continue; case AST_TREE_TOKEN_TYPE_TYPE: @@ -153,6 +212,7 @@ CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot) { case AST_TREE_TOKEN_FUNCTION_CALL: case AST_TREE_TOKEN_TYPE_U64: case AST_TREE_TOKEN_VARIABLE_DEFINE: + case AST_TREE_TOKEN_OPERATOR_ASSIGN: case AST_TREE_TOKEN_NONE: break; } @@ -196,7 +256,7 @@ bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end, AstTreeSingleChild *metadata = tree.metadata; if (metadata->token == AST_TREE_TOKEN_VALUE_U64) { CodeGeneratorOperand *value = newCodeGeneratorOperand( - u64ToString((AstTreeU64)metadata->metadata), false); + (void *)(uint64_t)(AstTreeU64)metadata->metadata, false); generateCodePushCode( codes, createGenerateCode(label_begin, label_end, @@ -205,7 +265,7 @@ bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end, AstTreeVariable *variable = metadata->metadata; if (variable->isConst) { CodeGeneratorOperand *value = newCodeGeneratorOperand( - u64ToString((AstTreeU64)variable->value->metadata), false); + (void *)(uint64_t)(AstTreeU64)variable->value->metadata, false); generateCodePushCode( codes, createGenerateCode(label_begin, label_end, @@ -239,17 +299,19 @@ bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end, } CodeGeneratorDoubleOperand *operands = a404m_malloc(sizeof(*operands)); - CodeGeneratorOperand *op0 = makeCodeGeneratorOperand(infix->left); - CodeGeneratorOperand *op1 = makeCodeGeneratorOperand(infix->right); + CodeGeneratorOperand *op0 = + newCodeGeneratorOperandFromAstTree(infix->left); + CodeGeneratorOperand *op1 = + newCodeGeneratorOperandFromAstTree(infix->right); operands->op0 = *op0; operands->op1 = *op1; free(op0); free(op1); - generateCodePushCode( - codes, - createGenerateCode(label_begin, label_end, - CODE_GENERATOR_INSTRUCTION_MOV_U64, operands)); + generateCodePushCode(codes, + createGenerateCode(label_begin, label_end, + CODE_GENERATOR_INSTRUCTION_MOV_64, + operands)); } goto OK; case AST_TREE_TOKEN_VARIABLE_DEFINE: @@ -277,10 +339,17 @@ bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end, } static const char TEMPLATE[] = "include 'stdlib/main.asm'\n"; - static const size_t TEMPLATE_LEN = sizeof(TEMPLATE) / sizeof(*TEMPLATE) - sizeof(*TEMPLATE); +static const char EXEC_SEGMENT[] = "segment readable executable\n"; +static const size_t EXEC_SEGMENT_LEN = + sizeof(EXEC_SEGMENT) / sizeof(*EXEC_SEGMENT) - sizeof(*EXEC_SEGMENT); + +static const char DATA_SEGMENT[] = "segment readable writable\n"; +static const size_t DATA_SEGMENT_LEN = + sizeof(DATA_SEGMENT) / sizeof(*DATA_SEGMENT) - sizeof(*DATA_SEGMENT); + static void codeGeneratorAppendFlatASMCommand(char **fasm, size_t *fasm_size, size_t *fasm_inserted, const char *str, size_t str_len) { @@ -301,6 +370,9 @@ char *codeGeneratorToFlatASM(const CodeGeneratorCodes *codes) { codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, TEMPLATE, TEMPLATE_LEN); + codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, + EXEC_SEGMENT, EXEC_SEGMENT_LEN); + for (size_t i = 0; i < codes->codes_size; ++i) { const CodeGeneratorCode code = codes->codes[i]; if (code.label_begin != code.label_end) { @@ -317,9 +389,10 @@ char *codeGeneratorToFlatASM(const CodeGeneratorCodes *codes) { CodeGeneratorOperand *metadata = code.metadata; char *inst; if (metadata->isReference) { - asprintf(&inst, "mov rdi,[%s]\ncall print_u64\n", metadata->value); + asprintf(&inst, "mov rdi,[%s]\ncall print_u64\n", + metadata->value.reference); } else { - asprintf(&inst, "mov rdi,%s\ncall print_u64\n", metadata->value); + asprintf(&inst, "mov rdi,%lu\ncall print_u64\n", metadata->value.value); } codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, inst, strlen(inst)); @@ -348,30 +421,30 @@ char *codeGeneratorToFlatASM(const CodeGeneratorCodes *codes) { CodeGeneratorOperand *metadata = code.metadata; char *inst; if (metadata->isReference) { - asprintf(&inst, "dq [%s]\n", metadata->value); + asprintf(&inst, "dq [%s]\n", metadata->value.reference); } else { - asprintf(&inst, "dq %s\n", metadata->value); + asprintf(&inst, "dq %lu\n", metadata->value.value); } codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, inst, strlen(inst)); free(inst); } continue; - case CODE_GENERATOR_INSTRUCTION_MOV_U64: { + case CODE_GENERATOR_INSTRUCTION_MOV_64: { CodeGeneratorDoubleOperand *metadata = code.metadata; char *inst; - if (metadata->op1.isReference) { - asprintf(&inst, "mov rax, [%s]\n", metadata->op1.value); + if (metadata->op0.isReference) { + asprintf(&inst, "mov64 [%s],", metadata->op0.value.reference); } else { - asprintf(&inst, "mov rax, %s\n", metadata->op1.value); + UNREACHABLE; } codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, inst, strlen(inst)); free(inst); - if (metadata->op0.isReference) { - asprintf(&inst, "mov [%s], rax\n", metadata->op0.value); + if (metadata->op1.isReference) { + asprintf(&inst, "[%s]\n", metadata->op1.value.reference); } else { - UNREACHABLE; + asprintf(&inst, "%lu\n", metadata->op1.value.value); } codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, inst, strlen(inst)); @@ -379,7 +452,35 @@ char *codeGeneratorToFlatASM(const CodeGeneratorCodes *codes) { } continue; } - printLog("Bad instruction %d", code.instruction); + UNREACHABLE; + } + + codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, + DATA_SEGMENT, DATA_SEGMENT_LEN); + + for (size_t i = 0; i < codes->defines_size; ++i) { + const CodeGeneratorDefine define = codes->defines[i]; + + switch (define.type) { + case CODE_GENERATOR_TYPE_64: + CodeGeneratorOperand operand = define.operand; + char *inst; + if (operand.isReference) { + asprintf(&inst, "def64 %.*s, [%s]\n", + (int)(define.label_end - define.label_begin), + define.label_begin, operand.value.reference); + } else { + asprintf(&inst, "def64 %.*s, %lu\n", + (int)(define.label_end - define.label_begin), + define.label_begin, operand.value.value); + } + codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, inst, + strlen(inst)); + free(inst); + + continue; + } + UNREACHABLE; } fasm[fasm_inserted] = '\0'; diff --git a/src/compiler/code-generator.h b/src/compiler/code-generator.h index ac47e76..0c388b9 100644 --- a/src/compiler/code-generator.h +++ b/src/compiler/code-generator.h @@ -9,9 +9,13 @@ typedef enum CodeGeneratorInstruction : uint8_t { CODE_GENERATOR_INSTRUCTION_CALL, CODE_GENERATOR_INSTRUCTION_RET, CODE_GENERATOR_INSTRUCTION_DEF_VAR64, - CODE_GENERATOR_INSTRUCTION_MOV_U64, + CODE_GENERATOR_INSTRUCTION_MOV_64, } CodeGeneratorInstruction; +typedef enum CodeGeneratorType : uint8_t { + CODE_GENERATOR_TYPE_64, +} CodeGeneratorType; + typedef struct CodeGeneratorCode { char *label_begin; char *label_end; @@ -25,7 +29,10 @@ typedef struct CodeGeneratorCall { } CodeGeneratorCall; typedef struct CodeGeneratorOperand { - char *value; + union { + uint64_t value; + char *reference; + } value; bool isReference; } CodeGeneratorOperand; @@ -34,25 +41,42 @@ typedef struct CodeGeneratorDoubleOperand { CodeGeneratorOperand op1; } CodeGeneratorDoubleOperand; +typedef struct CodeGeneratorDefine { + char *label_begin; + char *label_end; + CodeGeneratorOperand operand; + CodeGeneratorType type; +} CodeGeneratorDefine; + typedef struct CodeGeneratorCodes { CodeGeneratorCode *codes; size_t codes_size; + CodeGeneratorDefine *defines; + size_t defines_size; } CodeGeneratorCodes; +void codeGeneratorOperandDestroy(CodeGeneratorOperand operand); void codeGeneratorDelete(CodeGeneratorCodes *code); -CodeGeneratorOperand *newCodeGeneratorOperand(char *value, bool isReference); +CodeGeneratorOperand *newCodeGeneratorOperand(void *value, bool isReference); +CodeGeneratorOperand makeCodeGeneratorOperand(void *value, bool isReference); -CodeGeneratorOperand *makeCodeGeneratorOperand(AstTree tree); +CodeGeneratorOperand *newCodeGeneratorOperandFromAstTree(AstTree tree); CodeGeneratorCode createGenerateCode(char *label_begin, char *label_end, CodeGeneratorInstruction instruction, void *metadata); +CodeGeneratorDefine createGenerateDefine(char *label_begin, char *label_end, + CodeGeneratorOperand operand, + CodeGeneratorType type); + CodeGeneratorCode *newGenerateCode(char *label_begin, char *label_end, CodeGeneratorInstruction instruction); void generateCodePushCode(CodeGeneratorCodes *codes, CodeGeneratorCode code); +void generateCodePushDefine(CodeGeneratorCodes *codes, + CodeGeneratorDefine define); CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot); diff --git a/stdlib/main.asm b/stdlib/main.asm index 9a78d8e..efa7ba0 100644 --- a/stdlib/main.asm +++ b/stdlib/main.asm @@ -4,6 +4,16 @@ SYS_exit = 60 SYS_write = 1 STDOUT = 1 +macro mov64 dest, src { + mov rax, src + mov dest, rax +} + +macro def64 name, value { +name: + dq value +} + segment readable executable entry _start @@ -38,4 +48,3 @@ mov rax, SYS_exit xor rdi,rdi syscall -segment readable executable writable |