aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.c
diff options
context:
space:
mode:
authorElis Eriksson <spelis@spelis.li>2026-06-20 20:12:29 +0200
committerElis Eriksson <spelis@spelis.li>2026-06-20 20:12:29 +0200
commit38942c34a497a4c6edf080dc64440c1bc486fc46 (patch)
tree8fd3c891dff03f649b21aeb02c594e3e50f3160c /src/codegen.c
parentde91ec0542aea5959376ee0d2c9d486268dd9392 (diff)
downloadbfc-38942c34a497a4c6edf080dc64440c1bc486fc46.tar
bfc-38942c34a497a4c6edf080dc64440c1bc486fc46.tar.gz
bfc-38942c34a497a4c6edf080dc64440c1bc486fc46.tar.bz2
bfc-38942c34a497a4c6edf080dc64440c1bc486fc46.tar.lz
bfc-38942c34a497a4c6edf080dc64440c1bc486fc46.tar.xz
bfc-38942c34a497a4c6edf080dc64440c1bc486fc46.tar.zst
bfc-38942c34a497a4c6edf080dc64440c1bc486fc46.zip
Pattern matching optimizer and more
it's not the best optimizer but it works. Also added a -ast_dump flag which dumps the AST to stderr. Also input is now done in raw mode just because it can be.
Diffstat (limited to 'src/codegen.c')
-rw-r--r--src/codegen.c81
1 files changed, 55 insertions, 26 deletions
diff --git a/src/codegen.c b/src/codegen.c
index a019af6..00a4e16 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -1,66 +1,95 @@
#include "all.h"
+#include "str.h"
static void emit_prelude(str *out) {
str_append(out, "void _start(void){"
- "uint8_t tape[30000]={0};"
- "uint8_t*ptr=tape+15000;");
+ "struct termios orig;"
+ "rawon(0, &orig);"
+ "u8 t[30000]={0};"
+ "u8*p=t+15000;");
}
static void emit_runtime(str *out) {
- str_append(out, "typedef unsigned long size_t;"
- "typedef unsigned char uint8_t;");
+ str_append(out, "typedef unsigned long sz;"
+ "typedef unsigned char u8;");
- 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;"
- "}");
+ str_append(out, "typedef unsigned int tcflag_t;"
+ "typedef unsigned char cc_t;"
+ "typedef unsigned int speed_t;");
+
+ str_append(out, "struct termios{tcflag_t c_iflag;tcflag_t c_oflag;tcflag_t "
+ "c_cflag;tcflag_t c_lflag;cc_t c_line;cc_t c_cc[19];speed_t "
+ "c_ispeed; speed_t c_ospeed;};");
+
+ str_append(out, "static inline long sys3(long n, long a1, long a2, long a3){"
+ "long ret;"
+ "__asm__ volatile ("
+ "\"syscall\""
+ ":\"=a\"(ret)"
+ ":\"a\"(n),\"D\"(a1),\"S\"(a2),\"d\"(a3)"
+ ":\"rcx\",\"r11\",\"memory\""
+ ");"
+ "return ret;"
+ "}");
+
+ str_append(out, "static void rawon(int fd,struct termios *orig){"
+ "sys3(16,fd,0x5401,(long)orig);"
+ "struct termios t=*orig;"
+ "t.c_lflag&=~(2|010|0100000);"
+ "t.c_cc[6]=1;"
+ "t.c_cc[5]=0;"
+ "sys3(16,fd,0x5402,(long)&t);"
+ "}");
+
+ str_append(out, "static void rawoff(int fd,struct termios *orig){"
+ "sys3(16,fd,0x5402,(long)orig);"
+ "}");
}
-static void emit_epilogue(str *out) { str_append(out, "syscall3(60,0,0,0);}"); }
+static void emit_epilogue(str *out) {
+ str_append(out, "rawoff(0,&orig);sys3(60,0,0,0);}");
+}
-void emit_node(str *out, ast_node_t *node, int indent) {
+void emit_node(str *out, ast_node_t *node) {
for (; node; node = node->next) {
switch (node->type) {
+
case AST_INC:
- str_appendf(out, "*ptr+=%d;", node->val);
+ str_appendf(out, "*p+=%d;", node->val);
break;
case AST_DEC:
- str_appendf(out, "*ptr-=%d;", node->val);
+ str_appendf(out, "*p-=%d;", node->val);
break;
case AST_PTR_INC:
- str_appendf(out, "ptr+=%d;", node->val);
+ str_appendf(out, "p+=%d;", node->val);
break;
case AST_PTR_DEC:
- str_appendf(out, "ptr-=%d;", node->val);
+ str_appendf(out, "p-=%d;", node->val);
break;
case AST_OUT:
- str_appendf(out, "syscall3(1,1,ptr,1);");
+ str_appendf(out, "sys3(1,1,(long)p,1);");
break;
case AST_IN:
- str_appendf(out, "syscall3(0,0,ptr,1);");
+ str_appendf(out, "sys3(0,0,(long)p,1);");
break;
case AST_LOOP:
- str_append(out, "while(*ptr){");
+ str_append(out, "while(*p){");
for (size_t i = 0; i < node->children.len; i++) {
- emit_node(out, node->children._data[i], indent + 1);
+ emit_node(out, node->children._data[i]);
}
str_append(out, "}");
break;
+ case AST_CLEAR:
+ str_append(out, "*p=0;");
+ break;
}
}
}
@@ -70,7 +99,7 @@ str gen_code(ast_node_t *ast) {
emit_runtime(&out);
emit_prelude(&out);
- emit_node(&out, ast, 1);
+ emit_node(&out, ast);
emit_epilogue(&out);
return out;