]> git.mdlowis.com Git - proto/obnc.git/commitdiff
started fleshing out a C backend
authorMichael D. Lowis <mike.lowis@gentex.com>
Wed, 28 Apr 2021 17:44:49 +0000 (13:44 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Wed, 28 Apr 2021 17:44:49 +0000 (13:44 -0400)
cerise/backend/c99/codegen.c [new file with mode: 0644]
cerise/backend/test/codegen.c
cerise/backend/x86_64/codegen.c
cerise/build.sh
cerise/inc/cerise.h
cerise/src/const_ops.c
cerise/src/parser.c
cerise/tests/Module.m
cerise/tests/Module.s

diff --git a/cerise/backend/c99/codegen.c b/cerise/backend/c99/codegen.c
new file mode 100644 (file)
index 0000000..1d8da23
--- /dev/null
@@ -0,0 +1,185 @@
+#include "cerise.h"
+#include <limits.h>
+#include <assert.h>
+
+Type BoolType = {
+    .form = FORM_BOOL,
+    .size = sizeof(bool)
+};
+
+Type IntType = {
+    .form = FORM_INT,
+    .size = sizeof(long)
+};
+
+Type RealType = {
+    .form = FORM_REAL,
+    .size = sizeof(double)
+};
+
+Type StringType = {
+    .form = FORM_STRING,
+    .size = -1
+};
+
+static char* TypeNames[] = {
+    [FORM_BOOL]   = "bool",
+    [FORM_INT]    = "long",
+    [FORM_REAL]   = "double",
+    [FORM_STRING] = "char*"
+};
+
+static char* BinaryOps[] = {
+    ['+'] = "+",
+    ['-'] = "-",
+    ['*'] = "*",
+    ['/'] = "/",
+    ['%'] = "%",
+};
+
+static void load_var(Parser* p, Item* item)
+{
+    (void)p;
+    switch (item->mode)
+    {
+        case ITEM_CONST:
+            /* TODO: range check the constant */
+            printf("    const %s _T%d = %lld;\n",
+                TypeNames[item->type->form], p->curr_reg, item->imm.i);
+            item->reg = p->curr_reg;
+            p->curr_reg++;
+
+        case ITEM_VAR:
+            break;
+
+        case ITEM_MVAR:
+            /* TODO: range check the constant */
+            printf("    const %s _T%d = %s_%s;\n",
+                TypeNames[item->type->form], p->curr_reg, p->name, item->imm.s);
+            item->reg = p->curr_reg;
+            p->curr_reg++;
+            break;
+
+        case ITEM_REG:
+            /* nothing to do */
+            break;
+    }
+}
+
+/* Operators
+ *****************************************************************************/
+void binary_op(Parser* p, int op, Item* a, Item* b)
+{
+    char* type = TypeNames[a->type->form];
+    char* oper = BinaryOps[op];
+    printf("    const %s _T%d = _T%d %s _T%d;\n",
+        type, p->curr_reg, a->reg, oper, b->reg);
+    a->reg = p->curr_reg;
+    p->curr_reg++;
+}
+
+/* Public Interface
+ *****************************************************************************/
+void codegen_setint(Item* item, Type* type, long long val)
+{
+    item->mode  = ITEM_CONST;
+    item->type  = type;
+    item->reg   = 0;
+    item->imm.i = val;
+}
+
+void codegen_setreal(Item* item, double val)
+{
+    item->mode  = ITEM_CONST;
+    item->type  = &RealType;
+    item->reg   = 0;
+    item->imm.f = val;
+}
+
+void codegen_setstr(Item* item, char* val)
+{
+    item->mode  = ITEM_CONST;
+    item->type  = &StringType;
+    item->reg   = 0;
+    item->imm.s = val;
+}
+
+void codegen_imports(Parser* p)
+{
+    (void)p;
+}
+
+void codegen_global(Parser* p, char* name, Type* type)
+{
+    printf("%s %s_%s;\n", TypeNames[type->form], p->name, name);
+}
+
+void codegen_main(Parser* p)
+{
+    (void)p;
+    printf("\nint main(int argc, char** argv) {\n");
+    printf("    (void)argc, (void)argv;\n");
+    printf("    return 0;\n");
+    printf("}\n");
+}
+
+void codegen_startproc(Parser* p, char* name, bool exported)
+{
+    char* export = (exported ? "" : "static");
+    if (!name)
+    {
+        printf("\n%svoid %s(void) {\n", export, p->name);
+    }
+    else
+    {
+        assert(!"not implemented");
+    }
+}
+
+void codegen_endproc(Parser* p)
+{
+    printf("}\n");
+    (void)p;
+}
+
+void codegen_unop(Parser* p, int op, Item* a)
+{
+    if (a->mode == ITEM_CONST)
+    {
+        const_unop(p, op, a);
+    }
+    else
+    {
+        assert(!"not supported");
+    }
+}
+
+void codegen_binop(Parser* p, int op, Item* a, Item* b)
+{
+    if (items_const(a, b))
+    {
+        const_binop(op, a, b);
+    }
+    else
+    {
+        load_var(p, a);
+        load_var(p, b);
+        binary_op(p, op, a, b);
+    }
+}
+
+void codegen_store(Parser* p, Item* a, Item* b)
+{
+    if (a->mode == ITEM_MVAR && b->reg == 0)
+    {
+        printf("    %s_%s = %lld;\n", p->name, a->imm.s, b->imm.i);
+    }
+    else if (a->mode == ITEM_MVAR)
+    {
+        printf("    %s_%s = _T%d;\n", p->name, a->imm.s, b->reg);
+    }
+    else
+    {
+        assert(!"bad store op");
+    }
+}
index b52c404fc2ef6d654e0b6e7a1837770732c9343d..fa252c69998e946c3b0887f0c36bab5e15ccd211 100644 (file)
@@ -61,9 +61,9 @@ void codegen_main(Parser* p)
     (void)p;
 }
 
-void codegen_startproc(Parser* p, char* name, long long localsz)
+void codegen_startproc(Parser* p, char* name, bool exported)
 {
-    (void)p, (void)name, (void)localsz;
+    (void)p, (void)name, (void)exported;
 }
 
 void codegen_endproc(Parser* p)
index ee68ad40e2ace8d608dac9126cfc3133f8f958b8..ac961a68b94c3b8e7386270be99b1c1b470a8b0b 100644 (file)
@@ -177,11 +177,6 @@ void codegen_setstr(Item* item, char* val)
     item->imm.s = val;
 }
 
-static int items_const(Item* a, Item* b)
-{
-    return ((a->mode == ITEM_CONST) && (b->mode == ITEM_CONST));
-}
-
 static void load_var(Parser* p, Item* item)
 {
     (void)p;
@@ -241,7 +236,7 @@ void codegen_main(Parser* p)
     printf("    ret\n");
 }
 
-void codegen_startproc(Parser* p, char* name, long long localsz)
+void codegen_startproc(Parser* p, char* name, bool exported)
 {
     printf("    .text\n");
     if (name)
@@ -254,17 +249,8 @@ void codegen_startproc(Parser* p, char* name, long long localsz)
         printf("    .globl %s\n", p->name);
         printf("%s:\n", p->name);
     }
-
     printf("    pushq   %%rbp\n");
-    if (localsz > 0)
-    {
-        printf("    movq    %%rsp, %%rbp\n");
-        printf("    sub     $%lld, %%rsp\n\n", localsz);
-    }
-    else
-    {
-        printf("    movq    %%rsp, %%rbp\n\n");
-    }
+    printf("    movq    %%rsp, %%rbp\n\n");
     p->curr_reg = 1;
 }
 
index 55e276527d26532740dd9f20af9037d64c8a64bd..258525ae86bca26ec2b4b8804763569b8d247a43 100755 (executable)
@@ -1,14 +1,15 @@
 #!/bin/sh
 
 CCCMD="cc -g -Wall -Wextra --std=c99 -Iinc/"
-BACKEND=backend/x86_64
 TEST_BACKEND=backend/test
 
 ctags -R &
-$CCCMD -D CERISE_TESTS -o cerisec-test src/*.c "$TEST_BACKEND"/*.c \
-  && $CCCMD -o cerisec src/*.c "$BACKEND"/*.c \
-  && ./cerisec-test \
-  && ./cerisec tests/Module.m | tee tests/Module.s \
-  && cc -o Module tests/Module.s
-rm Module
-#[ $? -gt 0 ] && printf "\a"
+
+   $CCCMD -D CERISE_TESTS -o cerisec-test src/*.c backend/test/*.c \
+&& $CCCMD -o cerisec src/*.c "backend/c99"/*.c \
+&& $CCCMD -o cerisec-x86_64 src/*.c "backend/x86_64"/*.c \
+&& ./cerisec-test \
+&& ./cerisec tests/Module.m
+
+rm -f Module
+
index 9632861eab5ebc16ac3cab133c1549d8cc2e8474..84ee627547786828ed97a75f8f4463f118e20200 100644 (file)
@@ -131,7 +131,7 @@ typedef struct {
     Module* imports;
     Symbol* scope;
     char* name;
-    long curr_reg;
+    int curr_reg;
 } Parser;
 
 static inline void item_dump(Item* a)
@@ -162,6 +162,7 @@ void compile(char* fname);
 
 /* Code Generation
  *****************************************************************************/
+int items_const(Item* a, Item* b);
 void const_binop(int op, Item* a, Item* b);
 void const_unop(Parser* p, int op, Item* a);
 
@@ -174,7 +175,7 @@ void codegen_setstr(Item* item, char* val);
 void codegen_imports(Parser* p);
 void codegen_global(Parser* p, char* name, Type* type);
 void codegen_main(Parser* p);
-void codegen_startproc(Parser* p, char* name, long long localsz);
+void codegen_startproc(Parser* p, char* name, bool exported);
 void codegen_endproc(Parser* p);
 void codegen_unop(Parser* p, int op, Item* a);
 void codegen_binop(Parser* p, int op, Item* a, Item* b);
index a627336dc95111a62e158a82cb374f4192b45f64..eedd955d139d893315cc2dcd7f1a8eebbb8c83c0 100644 (file)
@@ -1,5 +1,10 @@
 #include "cerise.h"
 
+int items_const(Item* a, Item* b)
+{
+    return ((a->mode == ITEM_CONST) && (b->mode == ITEM_CONST));
+}
+
 void const_binop(int op, Item* a, Item* b)
 {
     if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
index fed4f0306e90182a7abd4bd13c6fd450977a7b53..0c6f7469f50464c4905305e99e71e1bd6ebcbc4b 100644 (file)
@@ -597,7 +597,6 @@ RULE(statement_seq)
                 init_item(item, sym);
                 item->imm.s = sym->name;
 
-                printf("\n//  %s = ...\n", sym->name);
                 expression(p, &right);
                 check_types(p, item, &right);
                 codegen_store(p, item, &right);
@@ -685,7 +684,7 @@ RULE(module)
         var_decl(p, item);
     }
 
-    codegen_startproc(p, NULL, 0);
+    codegen_startproc(p, NULL, true);
     if (accept(p, BEGIN))
     {
         codegen_imports(p);
index f33cbfd2e2df9b1db20abaf91270fd28f0835e48..960e45cf28d2cad377180df5cc582106d2a66b45 100644 (file)
@@ -14,25 +14,29 @@ var
     c : Int
 
 begin
-#    a = true;
-#    a = A;
-#    b = 24;
-#    b = B;
+    a = true;
+    a = A;
+    b = 24;
+    b = B;
+
+    # Unary ops
+#    b = +b;
+#    b = -b;
 
     # Immediate ops
     c = b + 1;
-#    c = b - 1;
-#    c = b * 1;
+    c = b - 1;
+    c = b * 1;
 
 #    c = b == 1;
 
     # Register ops
-#    c = 1 + b;
-#    c = 1 - b;
-#    c = 1 * b;
+    c = 1 + b;
+    c = 1 - b;
+    c = 1 * b;
 
-#    c = b + b;
+    c = b + b;
 
     # Complex arithmetic
-#    c = b + b * b + b
+    c = b + b * b + b;
 end
index d39ed315d3836157dc7d91257f0b7bc995cc9193..6c0af9f434a2c643850a79f16fbcd445f614444f 100644 (file)
@@ -1,36 +1,5 @@
-    .data
-Module_a:
-    .zero 1
-
-    .data
-Module_b:
-    .zero 8
-
-    .data
-Module_c:
-    .zero 8
-
-    .text
-    .globl Module
-Module:
-    pushq   %rbp
-    movq    %rsp, %rbp
-
+a
+b
+c
 
 //  c = ...
-    movq    Module_b(%rip), %rdi
-    addq   $1, %rdi
-    movq    %rdi, Module_c(%rip)
-
-    pop     %rbp
-    ret
-
-    .text
-    .globl main
-main:
-    pushq   %rbp
-    movq    %rsp, %rbp
-    call    Module
-    xor     %rax, %rax
-    pop     %rbp
-    ret