aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen.c')
-rw-r--r--src/codegen.c125
1 files changed, 27 insertions, 98 deletions
diff --git a/src/codegen.c b/src/codegen.c
index e4972db..a019af6 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -1,133 +1,65 @@
#include "all.h"
-#include "str.h"
-static void emit_includes(str *out) {
- str_append(out, "#include <stdio.h>\n");
- str_append(out, "#include <stdlib.h>\n");
- str_append(out, "#include <string.h>\n\n");
+static void emit_prelude(str *out) {
+ str_append(out, "void _start(void){"
+ "uint8_t tape[30000]={0};"
+ "uint8_t*ptr=tape+15000;");
}
static void emit_runtime(str *out) {
- str_append(
- out,
- "typedef struct {\n"
- " unsigned char *data;\n"
- " size_t size;\n"
- "} tape_t;\n\n"
-
- "static void tape_init(tape_t *t, size_t initial) {\n"
- " t->data = calloc(initial, 1);\n"
- " t->size = initial;\n"
- "}\n\n"
-
- "static void tape_grow_right(tape_t *t, size_t needed) {\n"
- " size_t new_size = t->size;\n"
- " while (new_size <= needed) new_size *= 2;\n"
- " unsigned char *new_data = calloc(new_size, 1);\n"
- " memcpy(new_data, t->data, t->size);\n"
- " free(t->data);\n"
- " t->data = new_data;\n"
- " t->size = new_size;\n"
- "}\n\n"
-
- "static void tape_grow_left(tape_t *t, size_t add, size_t *ptr) {\n"
- " size_t new_size = t->size + add;\n"
- " unsigned char *new_data = calloc(new_size, 1);\n"
- " memcpy(new_data + add, t->data, t->size);\n"
- " free(t->data);\n"
- " t->data = new_data;\n"
- " t->size = new_size;\n"
- " *ptr += add;\n"
- "}\n\n"
+ str_append(out, "typedef unsigned long size_t;"
+ "typedef unsigned char uint8_t;");
- "static void tape_move_right(tape_t *t, size_t *ptr, size_t amount) {\n"
- " *ptr += amount;\n"
- " if (*ptr >= t->size)\n"
- " tape_grow_right(t, *ptr);\n"
- "}\n\n"
-
- "static void tape_move_left(tape_t *t, size_t *ptr, size_t amount) {\n"
- " if (amount > *ptr) {\n"
- " size_t need = amount - *ptr;\n"
- " size_t add = t->size;\n"
- " while (add <= need)\n"
- " add *= 2;\n"
- " tape_grow_left(t, add, ptr);\n"
- " }\n"
- " *ptr -= amount;\n"
- "}\n\n");
+ str_append(out,
+ "static inline long syscall3(long n, long a1, void *a2, long a3){"
+ "long ret;"
+ "__asm__ volatile ("
+ "\"syscall\""
+ ":\"=a\"(ret)"
+ ":\"a\"(n),\"D\"(a1),\"S\"(a2),\"d\"(a3)"
+ ":\"rcx\",\"r11\",\"memory\""
+ ");"
+ "return ret;"
+ "}");
}
-static void emit_prelude(str *out) {
- str_append(out, "int main(void)\n"
- "{\n"
- " tape_t tape;\n"
- " tape_init(&tape, 32);\n"
- " size_t ptr = tape.size / 2;\n\n");
-}
-
-static void emit_epilogue(str *out) {
- str_append(out, " free(tape.data);\n"
- " return 0;\n"
- "}\n");
-}
-
-static void emit_indent(str *out, int indent) {
- for (int i = 0; i < indent; i++)
- str_append(out, " ");
-}
+static void emit_epilogue(str *out) { str_append(out, "syscall3(60,0,0,0);}"); }
void emit_node(str *out, ast_node_t *node, int indent) {
for (; node; node = node->next) {
switch (node->type) {
case AST_INC:
- emit_indent(out, indent);
- str_append(out, "tape.data[ptr] += ");
- str_appendf(out, "%d;\n", node->val);
+ str_appendf(out, "*ptr+=%d;", node->val);
break;
case AST_DEC:
- emit_indent(out, indent);
- str_append(out, "tape.data[ptr] -= ");
- str_appendf(out, "%d;\n", node->val);
+ str_appendf(out, "*ptr-=%d;", node->val);
break;
case AST_PTR_INC:
- emit_indent(out, indent);
- str_append(out, "tape_move_right(&tape, &ptr, ");
- str_appendf(out, "%d", node->val);
- str_append(out, ");\n");
+ str_appendf(out, "ptr+=%d;", node->val);
break;
case AST_PTR_DEC:
- emit_indent(out, indent);
- str_append(out, "tape_move_left(&tape, &ptr, ");
- str_appendf(out, "%d", node->val);
- str_append(out, ");\n");
+ str_appendf(out, "ptr-=%d;", node->val);
break;
case AST_OUT:
- emit_indent(out, indent);
- str_append(out, "putchar((int)tape.data[ptr]);\n");
+ str_appendf(out, "syscall3(1,1,ptr,1);");
break;
case AST_IN:
- emit_indent(out, indent);
- str_append(out,
- "{ int ch = getchar();\n"
- " tape.data[ptr] = (ch == EOF) ? 0 : (unsigned char)ch; }\n");
+ str_appendf(out, "syscall3(0,0,ptr,1);");
break;
case AST_LOOP:
- emit_indent(out, indent);
- str_append(out, "while (tape.data[ptr]) {\n");
+ str_append(out, "while(*ptr){");
- for (int i = 0; i < node->children.len; i++) {
+ for (size_t i = 0; i < node->children.len; i++) {
emit_node(out, node->children._data[i], indent + 1);
}
- emit_indent(out, indent);
- str_append(out, "}\n");
+ str_append(out, "}");
break;
}
}
@@ -136,12 +68,9 @@ void emit_node(str *out, ast_node_t *node, int indent) {
str gen_code(ast_node_t *ast) {
str out = {0};
- emit_includes(&out);
emit_runtime(&out);
emit_prelude(&out);
-
emit_node(&out, ast, 1);
-
emit_epilogue(&out);
return out;