From f9352cf59fa5c628fdd3cc9b3f0a062c33d40445 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Thu, 22 Jan 2026 19:09:26 +1100 Subject: [PATCH] Start work on floats --- src/compiler.c | 184 ++++++++++++++++++++++++++++++++++++++++--------- src/compiler.h | 9 +++ 2 files changed, 161 insertions(+), 32 deletions(-) diff --git a/src/compiler.c b/src/compiler.c index 783117d..c61d68f 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -4,6 +4,7 @@ #include "include/estr.h" #include #include +#include VariableTable createVariableTable() { VariableTable vt; @@ -52,6 +53,39 @@ int getVariablePos(VariableTable* vt, const char* name) { return -1; } +DoubleTable createDoubleTable() { + DoubleTable dt; + dt.count = 0; + dt.capacity = 16; + dt.constants = malloc(sizeof(DoubleConstant) * 16); + return dt; +} + +char* addDoubleConstant(DoubleTable* dt, Estr* rodata, double value, int* counter) { + for (size_t i = 0; i < dt->count; i++) { + if (dt->constants[i].value == value) { + return dt->constants[i].label; + } + } + + if (dt->count >= dt->capacity) { + dt->capacity = dt->capacity == 0 ? 16 : dt->capacity * 2; + dt->constants = realloc(dt->constants, sizeof(DoubleConstant) * dt->capacity); + } + + char label[64]; + snprintf(label, sizeof(label), "float_const_%d", (*counter)++); + strcpy(dt->constants[dt->count].label, label); + dt->constants[dt->count].value = value; + dt->count++; + + char line[128]; + snprintf(line, 128, "%s: dq %.17g ; double constant\n", label, value); + APPEND_ESTR((*rodata), line); + + return dt->constants[dt->count - 1].label; +} + GroundValueType getInstructionReturnType(GroundInstruction* gi, VariableTable* table) { switch (gi->type) { case JUMP: @@ -287,6 +321,50 @@ GroundValueType getInstructionReturnType(GroundInstruction* gi, VariableTable* t return INT; } +char* processValueString(GroundArg arg, VariableTable* vt, GroundValueType* outType, DoubleTable* dt, Estr* rodata, int* doubleCounter) { + if (arg.type == VALREF) { + VariableInfo* var = getVariable(vt, arg.value.refName); + if (var && outType) *outType = var->type; + char* buf = malloc(260); + snprintf(buf, 260, "[%s]", arg.value.refName); + return buf; + } + if (arg.type == VALUE) { + if (outType) *outType = arg.value.value.type; + switch(arg.value.value.type) { + case INT: { + char* buf = malloc(64); + snprintf(buf, 64, "%" PRId64, arg.value.value.data.intVal); + return buf; + break; + } + case DOUBLE: { + char* label = addDoubleConstant(dt, rodata, arg.value.value.data.doubleVal, doubleCounter); + char* buf = malloc(128); + snprintf(buf, 128, "[rel %s]", label); + return buf; + break; + } + case BOOL: + return arg.value.value.data.boolVal ? "1" : "0"; + break; + case CHAR: { + char* buf = malloc(8); + snprintf(buf, 8, "%d", (int)arg.value.value.data.charVal); + return buf; + break; + } + default: { + printf("For now, only int, bool, and char are supported data types in the compiler."); + exit(1); + break; + } + } + } + return NULL; +} + +/* char* processValueString(GroundArg arg) { if (arg.type == VALREF) { char* buf = malloc(sizeof(char) * 260); @@ -320,11 +398,17 @@ char* processValueString(GroundArg arg) { } return NULL; } +*/ char* compileGroundProgram(GroundProgram* program) { Estr start = CREATE_ESTR("global _start\nsection .text\n_start:\n"); Estr data = CREATE_ESTR("section .bss\n"); Estr helpers = CREATE_ESTR(""); + Estr rodata = CREATE_ESTR("section .rodata\n"); + APPEND_ESTR(rodata, " newline_char: db 10\n"); + APPEND_ESTR(rodata, " space_char: db 32\n"); + DoubleTable doubleTable = createDoubleTable(); + int doubleConstCounter = 0; APPEND_ESTR(helpers, "\n; Helper: Print integer in rax\n"); APPEND_ESTR(helpers, "print_int:\n"); @@ -427,7 +511,7 @@ char* compileGroundProgram(GroundProgram* program) { APPEND_ESTR(start, " ; set\n") APPEND_ESTR(start, " mov rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[1])); + APPEND_ESTR(start, processValueString(gi.args.args[1], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " mov ["); APPEND_ESTR(start, varName); @@ -473,7 +557,7 @@ char* compileGroundProgram(GroundProgram* program) { APPEND_ESTR(start, " ; if\n"); APPEND_ESTR(start, " mov rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[0])); + APPEND_ESTR(start, processValueString(gi.args.args[0], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " test rax, rax\n"); APPEND_ESTR(start, " jnz "); @@ -500,7 +584,7 @@ char* compileGroundProgram(GroundProgram* program) { APPEND_ESTR(start, " ; not\n"); APPEND_ESTR(start, " mov rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[0])); + APPEND_ESTR(start, processValueString(gi.args.args[0], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " xor rax, 1\n"); APPEND_ESTR(start, " mov ["); @@ -526,17 +610,55 @@ char* compileGroundProgram(GroundProgram* program) { runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 3", &gi, i); } - char* varName= gi.args.args[2].value.refName; - APPEND_ESTR(start, " ; add\n"); - APPEND_ESTR(start, " mov rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[0])); - APPEND_ESTR(start, "\n"); - APPEND_ESTR(start, " add rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[1])); - APPEND_ESTR(start, "\n"); - APPEND_ESTR(start, " mov ["); - APPEND_ESTR(start, varName); - APPEND_ESTR(start, "], rax\n"); + GroundValueType leftType, rightType; + + char* left = processValueString(gi.args.args[0], &varTable, &leftType, &doubleTable, &rodata, &doubleConstCounter); + char* right = processValueString(gi.args.args[1], &varTable, &rightType, &doubleTable, &rodata, &doubleConstCounter); + char* varName = gi.args.args[2].value.refName; + + bool isDouble = (leftType == DOUBLE || rightType == DOUBLE); + + if (isDouble) { + APPEND_ESTR(start, " ; add (double)\n"); + + if (leftType == INT) { + APPEND_ESTR(start, " mov rax, "); + APPEND_ESTR(start, left); + APPEND_ESTR(start, "\n"); + APPEND_ESTR(start, " cvtsi2sd xmm0, rax ; Convert int to double\n"); + } else { + APPEND_ESTR(start, " movsd xmm0, "); + APPEND_ESTR(start, left); + APPEND_ESTR(start, "\n"); + } + + if (rightType == INT) { + APPEND_ESTR(start, " mov rax, "); + APPEND_ESTR(start, right); + APPEND_ESTR(start, "\n"); + APPEND_ESTR(start, " cvtsi2sd xmm1, rax ; Convert int to double\n"); + APPEND_ESTR(start, " addsd xmm0, xmm1\n"); + } else { + APPEND_ESTR(start, " addsd xmm0, "); + APPEND_ESTR(start, right); + APPEND_ESTR(start, "\n"); + } + + APPEND_ESTR(start, " movsd ["); + APPEND_ESTR(start, varName); + APPEND_ESTR(start, "], xmm0\n"); + } else { + APPEND_ESTR(start, " ; add\n"); + APPEND_ESTR(start, " mov rax, "); + APPEND_ESTR(start, processValueString(gi.args.args[0], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); + APPEND_ESTR(start, "\n"); + APPEND_ESTR(start, " add rax, "); + APPEND_ESTR(start, processValueString(gi.args.args[1], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); + APPEND_ESTR(start, "\n"); + APPEND_ESTR(start, " mov ["); + APPEND_ESTR(start, varName); + APPEND_ESTR(start, "], rax\n"); + } break; } case SUBTRACT: { @@ -559,10 +681,10 @@ char* compileGroundProgram(GroundProgram* program) { char* varName= gi.args.args[2].value.refName; APPEND_ESTR(start, " ; subtract\n"); APPEND_ESTR(start, " mov rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[0])); + APPEND_ESTR(start, processValueString(gi.args.args[0], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " sub rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[1])); + APPEND_ESTR(start, processValueString(gi.args.args[1], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " mov ["); APPEND_ESTR(start, varName); @@ -589,10 +711,10 @@ char* compileGroundProgram(GroundProgram* program) { char* varName= gi.args.args[2].value.refName; APPEND_ESTR(start, " ; multiply\n"); APPEND_ESTR(start, " mov rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[0])); + APPEND_ESTR(start, processValueString(gi.args.args[0], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " imul rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[1])); + APPEND_ESTR(start, processValueString(gi.args.args[1], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " mov ["); APPEND_ESTR(start, varName); @@ -619,10 +741,10 @@ char* compileGroundProgram(GroundProgram* program) { char* varName= gi.args.args[2].value.refName; APPEND_ESTR(start, " ; equal\n"); APPEND_ESTR(start, " mov rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[0])); + APPEND_ESTR(start, processValueString(gi.args.args[0], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " cmp rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[1])); + APPEND_ESTR(start, processValueString(gi.args.args[1], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " sete al\n"); APPEND_ESTR(start, " movzx rax, al\n"); @@ -651,10 +773,10 @@ char* compileGroundProgram(GroundProgram* program) { char* varName= gi.args.args[2].value.refName; APPEND_ESTR(start, " ; inequal\n"); APPEND_ESTR(start, " mov rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[0])); + APPEND_ESTR(start, processValueString(gi.args.args[0], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " cmp rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[1])); + APPEND_ESTR(start, processValueString(gi.args.args[1], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " setne al\n"); APPEND_ESTR(start, " movzx rax, al\n"); @@ -683,10 +805,10 @@ char* compileGroundProgram(GroundProgram* program) { char* varName= gi.args.args[2].value.refName; APPEND_ESTR(start, " ; greater\n"); APPEND_ESTR(start, " mov rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[0])); + APPEND_ESTR(start, processValueString(gi.args.args[0], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " cmp rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[1])); + APPEND_ESTR(start, processValueString(gi.args.args[1], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " setg al\n"); APPEND_ESTR(start, " movzx rax, al\n"); @@ -715,10 +837,10 @@ char* compileGroundProgram(GroundProgram* program) { char* varName= gi.args.args[2].value.refName; APPEND_ESTR(start, " ; lesser\n"); APPEND_ESTR(start, " mov rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[0])); + APPEND_ESTR(start, processValueString(gi.args.args[0], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " cmp rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[1])); + APPEND_ESTR(start, processValueString(gi.args.args[1], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " setl al\n"); APPEND_ESTR(start, " movzx rax, al\n"); @@ -748,7 +870,7 @@ char* compileGroundProgram(GroundProgram* program) { } APPEND_ESTR(start, " ; print int\n"); APPEND_ESTR(start, " mov rax, "); - APPEND_ESTR(start, processValueString(gi.args.args[j])); + APPEND_ESTR(start, processValueString(gi.args.args[j], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " call print_int\n"); } @@ -773,7 +895,7 @@ char* compileGroundProgram(GroundProgram* program) { APPEND_ESTR(start, " ; end\n"); APPEND_ESTR(start, " mov rax, 60\n"); APPEND_ESTR(start, " mov rdi, "); - APPEND_ESTR(start, processValueString(gi.args.args[0])); + APPEND_ESTR(start, processValueString(gi.args.args[0], &varTable, NULL, &doubleTable, &rodata, &doubleConstCounter)); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " syscall\n"); break; @@ -793,10 +915,8 @@ char* compileGroundProgram(GroundProgram* program) { APPEND_ESTR(complete, start.str); APPEND_ESTR(complete, " ; End of program\n mov rax, 60\n mov rdi, 0\n syscall\n"); APPEND_ESTR(complete, helpers.str); - APPEND_ESTR(complete, "\nsection .rodata\n"); - APPEND_ESTR(complete, "newline_char: db 10\n"); - APPEND_ESTR(complete, "space_char: db 32\n"); - APPEND_ESTR(complete, data.str) + APPEND_ESTR(complete, data.str); + APPEND_ESTR(complete, rodata.str); return complete.str; } diff --git a/src/compiler.h b/src/compiler.h index ddcb7bf..0cd235a 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -16,4 +16,13 @@ typedef struct VariableTable { size_t capacity; } VariableTable; +typedef struct DoubleConstant { + double value; + char label[64]; +} DoubleConstant; +typedef struct DoubleTable { + DoubleConstant* constants; + size_t count; + size_t capacity; +} DoubleTable;