diff options
Diffstat (limited to 'src/compile.c')
| -rw-r--r-- | src/compile.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/src/compile.c b/src/compile.c new file mode 100644 index 0000000..5f4afeb --- /dev/null +++ b/src/compile.c @@ -0,0 +1,180 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "compile.h" +#include "hashtable.h" +#include "parse.h" + +int currentMangleId = 0; +int currentLitId = 0; +int includeStrlen = 0; +litData_t** literalData; + +litData_t* init_str_data(char* value) { + litData_t* litData = malloc(sizeof(litData_t)); + litData->litType = STRING; + char* vp = malloc((strlen(value) + 1) * sizeof(char)); + strcpy(vp, value); + litData->data = vp; + litData->id = currentLitId; + return litData; +} +char* compile_to_asm(sym_t* symbol) { + literalData = malloc(sizeof(litData_t) * 100); //100 literals + char* header = ".global _start\n.text\n_start: "; + char* program = compile_to_asm_internal(symbol, currentMangleId); + char* dataH = ".data\n"; + char* data = build_data(); + char* footer = "mov $60, %rax\n" + "xorl %rdi, %rdi\n" + "syscall\n"; + char* funcs = lib_funcs(); //build this last so it can consider contents of program + char* final = malloc(sizeof(char) * (strlen(header) + strlen(funcs) + strlen(program) + strlen(dataH) + strlen(data) + strlen(footer) + 1)); + strcpy(final, header); + strcat(final, program); + strcat(final, footer); + strcat(final, funcs); + strcat(final, dataH); + strcat(final, data); + return final; +} +char* build_data() { + //TODO: fix LABEL and non-STRING types + int l = 0; + char* out = ""; + for (int i = 0; i < currentLitId; i++) { + int lv = strlen((char*)literalData[i]->data); + int resl = 15 + lv; + char* line = malloc(sizeof(char) * (resl + 1)); + snprintf(line, resl + 1, "%cAA: .asciz \"%s\"\n", i + 65, (char*)literalData[i]->data); + if (i == 0) { + out = malloc(sizeof(char) * (resl + 1)); + } + else { + out = realloc(out, sizeof(char) * (l + resl + 1)); + } + strcpy(out + l, line); + l += resl; + } + return out; +} +char* lib_funcs() { + if (includeStrlen) { + return "strlen: xor %rax, %rax\n" + "dec %rax\n" + "strlen_count: inc %rax\n" + "cmpb $0x0, (%rdi,%rax,1)\n" + "jne strlen_count\n" + "ret\n"; + } + else { + return ""; + } +} +char* compile_to_asm_internal(sym_t* symbol, int mangleId) { + char* out; + if (symbol->province == LITERAL) { + /* store the symbol in .data */ + + if (symbol->litType == STRING) { + /* temporary implementation */ + literalData[currentLitId] = init_str_data((char*)symbol->name); + out = malloc(sizeof(char) * 16); + snprintf(out, 16, "mov $%cAA, \%rax\n", currentLitId + 65); + currentLitId++; + return out; + } + /*if (symbol->litType == INT) { + return init_sym_int(*((int*)symbol->name)); + } + else if (symbol->litType == FLOAT) { + return init_sym_float(*((float*)symbol->name)); + } + else if (symbol->litType == STRING) { + return init_sym_str((char*)symbol->name); + } + else { + return NULL; + }*/ + } + else if (symbol->province == KEY_REF) { + /* TODO: mangle */ + char* ir = try_comp_internal(symbol, ++currentMangleId); + if (ir != NULL) { + out = ir; + } + else { + + } + return out; + /*sym_t* returnV = NULL; + hashtable_t* newScope = init_hashtable(50, parentScope); + sym_t* ir = try_comp_internal(symbol, newScope); + if (ir != NULL) { + returnV = ir; + } + else { + pair_t p = hashtable_get_pair_recurse(parentScope, (char*)symbol->name); + if (p.key != NULL) { + sym_t* nextSym = (sym_t*)p.value; + if (symbol->argCount > 0) { + returnV = eval_with_args(nextSym, symbol->args, symbol->argCount, newScope); + } + else { + returnV = eval(nextSym, newScope); + } + } + else { + printf("key %s not found in any scope\n", (char*)symbol->name); + } + } + destroy_hashtable(newScope); + return returnV; */ + } + else { + printf("no symbol province\n"); + return NULL; + } +} +char* comp_all(sym_t** symbols, int count, int mangleId) { + int l = 0; + char* out; + for (int i = 0; i < count; i++) { + char* res = compile_to_asm_internal(symbols[i], mangleId); + int resl = strlen(res); + if (i == 0) { + out = malloc(sizeof(char) * (resl + 1)); + } + else { + out = realloc(out, sizeof(char) * (l + resl + 1)); + } + strcpy(out + l, res); + l += resl; + } + return out; +} +char* try_comp_internal(sym_t* symbol, int mangleId) { + unsigned int hash = get_hash((char*)symbol->name); + if (hash == get_hash("root")) { + //todo--add return wrapper for last + return comp_all(symbol->args, symbol->argCount, mangleId); + } + else if (hash == get_hash("print")) { + includeStrlen = 1; + /* execute the argument to receive rax--return value */ + char* pre = compile_to_asm_internal(symbol->args[0], mangleId); + char* body = "mov %rax, %rsi\n" + "mov %rsi, %rdi\n" + "call strlen\n" + "mov %rax, %rdx\n" + "mov $1, %rax\n" + "mov $1, %rdi\n" + "syscall\n"; + pre = realloc(pre, sizeof(char) * (strlen(pre) + strlen(body) + 1)); + strcat(pre, body); + return pre; + } + else { + return NULL; + } +} |
