diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | a.out | bin | 0 -> 1048 bytes | |||
| -rwxr-xr-x | out | bin | 0 -> 8992 bytes | |||
| -rw-r--r-- | src/compile.c | 180 | ||||
| -rw-r--r-- | src/compile.h | 17 | ||||
| -rw-r--r-- | src/precedent.c | 32 | ||||
| -rw-r--r-- | test_asm | 22 |
7 files changed, 242 insertions, 11 deletions
@@ -6,7 +6,7 @@ BINDIR ?= ${PREFIX}/bin MANDIR = ${PREFIX}/share/man generate: - $(CC) -o precedent src/precedent.c src/hashtable.c src/parse.c src/eval.c $(CFLAGS) + $(CC) -o precedent src/precedent.c src/hashtable.c src/parse.c src/eval.c src/compile.c $(CFLAGS) install: precedent install -d ${DESTDIR}${BINDIR} ${DESTDIR}${MANDIR}/man1 Binary files differBinary files differdiff --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; + } +} diff --git a/src/compile.h b/src/compile.h new file mode 100644 index 0000000..f4764c9 --- /dev/null +++ b/src/compile.h @@ -0,0 +1,17 @@ +#include "hashtable.h" +#include "parse.h" +#ifndef COMPILE +#define COMPILE +typedef struct LiteralData { + litType_t litType; + void* data; + int id; +} litData_t; +litData_t* init_str_data(char* value); +char* compile_to_asm(sym_t* symbol); +char* lib_funcs(); +char* compile_to_asm_internal(sym_t* symbol, int mangleId); +char* build_data(); +char* comp_all(sym_t** symbols, int count, int mangleId); +char* try_comp_internal(sym_t* symbol, int mangleId); +#endif diff --git a/src/precedent.c b/src/precedent.c index 44ca1ed..0b04b33 100644 --- a/src/precedent.c +++ b/src/precedent.c @@ -8,11 +8,13 @@ #include "hashtable.h" #include "parse.h" #include "eval.h" +#include "compile.h" int main(int argc, char** argv) { clock_t initTime = clock(); char visual = 0; char debug = 0; + char compiled = 0; if (argc > 1) { for (int i = 1; i < argc; i++) { if (strcmp("--version", argv[i]) == 0) { @@ -31,6 +33,9 @@ int main(int argc, char** argv) { else if (strcmp("--debug", argv[i]) == 0) { debug = 1; } + else if (strcmp("--compiled", argv[i]) == 0) { + compiled = 1; + } } } else { @@ -59,17 +64,24 @@ int main(int argc, char** argv) { write_symbol_visual(finalSymbol, 0); printf("--END VISUALIZATION--\n"); } - hashtable_t* rootTable = init_hashtable(500, NULL); - clock_t setupTime = clock(); - sym_t* sym = eval(finalSymbol, rootTable); - clock_t evalTime = clock(); - if (debug) { - printf("time taken to set up environment: %.5f secs\n", (float)(setupTime - initTime) / (float)CLOCKS_PER_SEC); - printf("time taken to execute program: %.5f secs\n", ((float)(evalTime - setupTime) - initTime) / (float)CLOCKS_PER_SEC); + if (compiled) { + char* res = compile_to_asm(finalSymbol); + destroy_sym_tree(finalSymbol); + printf("%s\n", res); + } + else { + hashtable_t* rootTable = init_hashtable(500, NULL); + clock_t setupTime = clock(); + sym_t* sym = eval(finalSymbol, rootTable); + clock_t evalTime = clock(); + if (debug) { + printf("time taken to set up environment: %.5f secs\n", (float)(setupTime - initTime) / (float)CLOCKS_PER_SEC); + printf("time taken to execute program: %.5f secs\n", ((float)(evalTime - setupTime) - initTime) / (float)CLOCKS_PER_SEC); + } + destroy_sym_tree(finalSymbol); + destroy_sym(sym); + destroy_hashtable(rootTable); } - destroy_sym_tree(finalSymbol); - destroy_sym(sym); - destroy_hashtable(rootTable); return 0; } char* read_file(char* path) { diff --git a/test_asm b/test_asm new file mode 100644 index 0000000..02c5b31 --- /dev/null +++ b/test_asm @@ -0,0 +1,22 @@ +.global _start +.text +_start: mov $AAA, %rax +mov %rax, %rsi +mov %rsi, %rdi +call strlen +mov %rax, %rdx +mov $1, %rax +mov $1, %rdi +syscall +mov $60, %rax +mov $0, %rdi +syscall +strlen: mov $0, %rax +dec %rax +strlen_count: inc %rax +cmpb $0x0, (%rdi,%rax,1) +jne strlen_count +ret +.data +AAA: .asciz "balalala\n" + |
