summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--a.outbin0 -> 1048 bytes
-rwxr-xr-xoutbin0 -> 8992 bytes
-rw-r--r--src/compile.c180
-rw-r--r--src/compile.h17
-rw-r--r--src/precedent.c32
-rw-r--r--test_asm22
7 files changed, 242 insertions, 11 deletions
diff --git a/Makefile b/Makefile
index 192ebc7..8aa4ed8 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/a.out b/a.out
new file mode 100644
index 0000000..6ea872c
--- /dev/null
+++ b/a.out
Binary files differ
diff --git a/out b/out
new file mode 100755
index 0000000..37de4e8
--- /dev/null
+++ b/out
Binary files differ
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;
+ }
+}
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"
+