]> git.mdlowis.com Git - proto/obnc.git/commitdiff
added more operations
authormike lowis <mike@mdlowis.com>
Wed, 28 Apr 2021 03:03:00 +0000 (23:03 -0400)
committermike lowis <mike@mdlowis.com>
Wed, 28 Apr 2021 03:03:00 +0000 (23:03 -0400)
cerise/cerise.h
cerise/codegen.c
cerise/const_ops.c [new file with mode: 0644]
cerise/tests/Module.m
cerise/tests/Module.s

index c784aaf0f370bb19dfd70e83febff6357addbe9e..9632861eab5ebc16ac3cab133c1549d8cc2e8474 100644 (file)
@@ -162,10 +162,8 @@ void compile(char* fname);
 
 /* Code Generation
  *****************************************************************************/
-enum Regs {
-    NOREG, RBX, RCX, RDX, RBP, RSP, RSI, RDI,
-    R8, R9, R10, R11, R12, R13, R14, R15,
-};
+void const_binop(int op, Item* a, Item* b);
+void const_unop(Parser* p, int op, Item* a);
 
 extern Type BoolType, IntType, RealType, StringType;
 
index 8e2f452f7eac8fffb28b4bdcf92fd9b8f9407436..4997696d6ef70c38f742c2bd952a37a317084f73 100644 (file)
 #include <limits.h>
 #include <assert.h>
 
-#define MAX_REG 15
-
-/* Register Usage
-
-*/
-
-Type BoolType = {
-    .form = FORM_BOOL,
-    .size = sizeof(bool)
+static char* RegNames[] = {
+    "%noreg", // invalid register
+    "%rdi",   // 1st argument
+    "%rsi",   // 2nd argument
+    "%rdx",   // 3rd argument
+    "%rcx",   // 4th argument
+    "%r8",    // 5th argument
+    "%r9",    // 6th argument
+    "%rbx",   // temp register
+    "%r10",   // temp register
+    "%r11",   // temp register
+    "%r12",   // callee saved register
+    "%r13",   // callee saved register
+    "%r14",   // callee saved register
+    "%r15",   // callee saved register
+//    "%rax",   // return value
 };
 
-Type IntType = {
-    .form = FORM_INT,
-    .size = sizeof(long)
-};
+#define MAX_REG (int)(sizeof(RegNames)/sizeof(RegNames[0]))
 
-Type RealType = {
-    .form = FORM_REAL,
-    .size = sizeof(double)
-};
-
-Type StringType = {
-    .form = FORM_STRING,
-    .size = -1
-};
+static char* regname(int reg)
+{
+    return RegNames[reg];
+}
 
-void codegen_setint(Item* item, Type* type, long long val)
+static char* curr_regname(Parser* p)
 {
-    item->mode  = ITEM_CONST;
-    item->type  = type;
-    item->reg   = NOREG;
-    item->imm.i = val;
+    return regname(p->curr_reg);
 }
 
-void codegen_setreal(Item* item, double val)
+static void next_reg(Parser* p)
 {
-    item->mode  = ITEM_CONST;
-    item->type  = &RealType;
-    item->reg   = NOREG;
-    item->imm.f = val;
+    if (p->curr_reg < MAX_REG)
+    {
+        p->curr_reg++;
+    }
+    else
+    {
+        assert(!"register stack overflow");
+    }
 }
 
-void codegen_setstr(Item* item, char* val)
+static void put_immop(char* op, int reg, long long imm)
 {
-    item->mode  = ITEM_CONST;
-    item->type  = &StringType;
-    item->reg   = NOREG;
-    item->imm.s = val;
+    printf("    %s   $%lld, %s\n", op, imm, regname(reg));
 }
 
-static int items_const(Item* a, Item* b)
+static void put_regop(char* op, int rega, int regb)
 {
-    return ((a->mode == ITEM_CONST) && (b->mode == ITEM_CONST));
+    printf("    %s   %s, %s\n", op, regname(regb), regname(rega));
 }
 
-static void const_binop(int op, Item* a, Item* b)
+static void imm_binop(Parser* p, int op, Item* a, Item* b)
 {
+    (void)p;
     if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
     {
         switch (op)
         {
-            case '+': a->imm.i = a->imm.i +  b->imm.i; break;
-            case '-': a->imm.i = a->imm.i -  b->imm.i; break;
-            case '*': a->imm.i = a->imm.i *  b->imm.i; break;
-            case '/': a->imm.i = a->imm.i /  b->imm.i; break;
-            case '%': a->imm.i = a->imm.i %  b->imm.i; break;
-            case AND: a->imm.i = a->imm.i && b->imm.i; break;
-            case OR:  a->imm.i = a->imm.i || b->imm.i; break;
-
-            case EQ:
-                a->imm.i = a->imm.i == b->imm.i;
-                a->type = &BoolType;
-                break;
-
-            case NEQ:
-                a->imm.i = a->imm.i != b->imm.i;
-                a->type = &BoolType;
+            case '+':
+                put_immop("addq", a->reg, b->imm.i);
                 break;
 
-            case '<':
-                a->imm.i = a->imm.i < b->imm.i;
-                a->type = &BoolType;
+            case '-':
+                put_immop("subq", a->reg, b->imm.i);
                 break;
 
-            case LTEQ:
-                a->imm.i = a->imm.i <= b->imm.i;
-                a->type = &BoolType;
+            case '*':
+                put_immop("imulq", a->reg, b->imm.i);
                 break;
 
-            case '>':
-                a->imm.i = a->imm.i > b->imm.i;
-                a->type = &BoolType;
-                break;
-
-            case GTEQ:
-                a->imm.i = a->imm.i >= b->imm.i;
-                a->type = &BoolType;
-                break;
-
-//            case IS:    break;
-
+//            case '/':
+//            case '%':
+//            case AND:
+//            case OR:
+
+//            case EQ:
+//        cmpq    %rax, %rdx
+//        setl    %al
+//        movzbl  %al, %eax
+//            case NEQ:
+//            case '<':
+//            case LTEQ:
+//            case '>':
+//            case GTEQ:
             default:
-                assert(!"not a valid op");
-                break;
+                assert(!"unimplemented immediate op");
         }
     }
-    else if (a->type->form == FORM_REAL)
+    else
+    {
+        assert(!"not implemented");
+    }
+}
+
+static void reg_binop(Parser* p, int op, Item* a, Item* b)
+{
+    if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
     {
         switch (op)
         {
-            case '+': a->imm.f = a->imm.f +  b->imm.f; break;
-            case '-': a->imm.f = a->imm.f -  b->imm.f; break;
-            case '*': a->imm.f = a->imm.f *  b->imm.f; break;
-            case '/': a->imm.f = a->imm.f /  b->imm.f; break;
-
-            case EQ:
-                a->imm.f = a->imm.f == b->imm.f;
-                a->type = &BoolType;
-                break;
-
-            case NEQ:
-                a->imm.f = a->imm.f != b->imm.f;
-                a->type = &BoolType;
+            case '+':
+                put_regop("addq", a->reg, b->reg);
                 break;
 
-            case '<':
-                a->imm.f = a->imm.f < b->imm.f;
-                a->type = &BoolType;
+            case '-':
+                put_regop("subq", a->reg, b->reg);
                 break;
 
-            case LTEQ:
-                a->imm.f = a->imm.f <= b->imm.f;
-                a->type = &BoolType;
-                break;
-
-            case '>':
-                a->imm.f = a->imm.f > b->imm.f;
-                a->type = &BoolType;
-                break;
-
-            case GTEQ:
-                a->imm.f = a->imm.f >= b->imm.f;
-                a->type = &BoolType;
+            case '*':
+                put_regop("imulq", a->reg, b->reg);
                 break;
 
+//            case '/':
+//            case '%':
+//            case AND:
+//            case OR:
+
+//            case EQ:
+//            case NEQ:
+//            case '<':
+//            case LTEQ:
+//            case '>':
+//            case GTEQ:
             default:
-                assert(!"not a valid op");
-                break;
+                assert(!"unimplemented immediate op");
         }
-    }
-    else
-    {
-        assert(!"not a valid form");
+        p->curr_reg--;
     }
 }
 
-static void const_unop(Parser* p, int op, Item* a)
+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
+};
+
+void codegen_setint(Item* item, Type* type, long long val)
 {
-    (void)p;
-    if (a->type->form == FORM_INT)
-    {
-        switch (op)
-        {
-            case '+': a->imm.i = +a->imm.i;      break;
-            case '-': a->imm.i = -a->imm.i;      break;
-            default:  assert(!"not a valid op"); break;
-        }
-    }
-    else if (a->type->form == FORM_REAL)
-    {
-        switch (op)
-        {
-            case '+': a->imm.f = +a->imm.f;      break;
-            case '-': a->imm.f = -a->imm.f;      break;
-            default:  assert(!"not a valid op"); break;
-        }
-    }
-    else if (a->type->form == FORM_BOOL)
-    {
-        switch (op)
-        {
-            case NOT: a->imm.i = !a->imm.i;      break;
-            default:  assert(!"not a valid op"); break;
-        }
-    }
-    else
-    {
-        assert(!"not a valid form");
-    }
+    item->mode  = ITEM_CONST;
+    item->type  = type;
+    item->reg   = 0;
+    item->imm.i = val;
 }
 
-static char* regname(int reg)
+void codegen_setreal(Item* item, double val)
 {
-    static char* names[] = {
-        "%noreg", // invalid register
-        "%rdi",   // 1st argument
-        "%rsi",   // 2nd argument
-        "%rdx",   // 3rd argument
-        "%rcx",   // 4th argument
-        "%r8",    // 5th argument
-        "%r9",    // 6th argument
-        "%rbx",   // temp register
-        "%r10",   // temp register
-        "%r11",   // temp register
-        "%r12",   // callee saved register
-        "%r13",   // callee saved register
-        "%r14",   // callee saved register
-        "%r15",   // callee saved register
-        "%rax",   // return value
-    };
-    return names[reg];
+    item->mode  = ITEM_CONST;
+    item->type  = &RealType;
+    item->reg   = 0;
+    item->imm.f = val;
 }
 
-static char* curr_regname(Parser* p)
+void codegen_setstr(Item* item, char* val)
 {
-    return regname(p->curr_reg);
+    item->mode  = ITEM_CONST;
+    item->type  = &StringType;
+    item->reg   = 0;
+    item->imm.s = val;
 }
 
-static void next_reg(Parser* p)
+static int items_const(Item* a, Item* b)
 {
-    if (p->curr_reg < MAX_REG)
-    {
-        p->curr_reg++;
-    }
-    else
-    {
-        assert(!"register stack overflow");
-    }
+    return ((a->mode == ITEM_CONST) && (b->mode == ITEM_CONST));
 }
 
 static void load_var(Parser* p, Item* item)
@@ -239,10 +189,7 @@ static void load_var(Parser* p, Item* item)
     {
         case ITEM_CONST:
             /* TODO: range check the constant */
-//            // emit instruction
-//            item->reg = p->curr_reg;
-
-            printf("    movq    %s, $%lld\n", curr_regname(p), item->imm.i);
+            put_immop("movq", p->curr_reg, item->imm.i);
             item->reg = p->curr_reg;
             next_reg(p);
             break;
@@ -253,17 +200,13 @@ static void load_var(Parser* p, Item* item)
         case ITEM_MVAR:
 //            puts("MVAR");
 //            printf("movq %s, $%lld\n", curr_regname(p), item->imm.i);
-
 //    item_dump(item);
 
-
             printf("    movq    %s_%s(%%rip), %s\n",
                 p->name,
                 item->imm.s,
                 curr_regname(p)
             );
-//                b->imm.i, p->name, a->imm.s);
-
             item->reg = p->curr_reg;
             next_reg(p);
             break;
@@ -349,44 +292,6 @@ void codegen_unop(Parser* p, int op, Item* a)
     }
 }
 
-static char* ImmOps[] = {
-    ['+'] = "addq",
-};
-
-static void imm_binop(Parser* p, int op, Item* a, Item* b)
-{
-    if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
-    {
-        char* opstring = ImmOps[op];
-        if (a->mode == ITEM_CONST)
-        {
-//            printf("    %s    $%lld, %s\n",
-//                opstring, regname(b->reg), a->imm.i, regname(b->reg));
-            printf("    %s    $%lld, %s\n",
-                opstring, a->imm.i, regname(b->reg));
-            a->reg = b->reg;
-        }
-        else
-        {
-            printf("    %s    $%lld, %s\n",
-                opstring, b->imm.i, regname(a->reg));
-        }
-    }
-    else
-    {
-        assert(!"not implemented");
-    }
-}
-
-static void imm_regop(Parser* p, int op, Item* a, Item* b)
-{
-    if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
-    {
-        printf("    addq    %s, %s, %s\n",
-            regname(a->reg), regname(b->reg), regname(b->reg));
-    }
-}
-
 void codegen_binop(Parser* p, int op, Item* a, Item* b)
 {
     if (items_const(a, b))
@@ -399,39 +304,19 @@ void codegen_binop(Parser* p, int op, Item* a, Item* b)
         imm_binop(p, op, a, b);
         p->curr_reg--;
     }
-    else if (a->mode == ITEM_CONST)
-    {
-        load_var(p, b);
-        imm_binop(p, op, a, b);
-        p->curr_reg--;
-    }
     else
     {
         load_var(p, a);
         load_var(p, b);
-        item_dump(a);
-        item_dump(b);
-
-        imm_regop(p, op, a, b);
-
-        // emit instruction
-        // p->topreg--;
-        // a->reg = p->topreg-1;
+        reg_binop(p, op, a, b);
+        p->curr_reg--;
+        a->reg = p->curr_reg;
     }
 }
 
-//  PROCEDURE Switch*(VAR x: Item);
-//  BEGIN Put1(Mov, RH, 0, -60); Put2(Ldw, RH, RH, 0);
-//    x.mode := Reg;
-//    x.type := intType;
-//    x.r := RH;
-//    INC(RH)
-//  END Switch;
-
-
 void codegen_store(Parser* p, Item* a, Item* b)
 {
-    if (a->mode == ITEM_MVAR && b->reg == NOREG)
+    if (a->mode == ITEM_MVAR && b->reg == 0)
     {
         printf("    movq    $%lld, %s_%s(%%rip)\n",
             b->imm.i, p->name, a->imm.s);
diff --git a/cerise/const_ops.c b/cerise/const_ops.c
new file mode 100644 (file)
index 0000000..a627336
--- /dev/null
@@ -0,0 +1,137 @@
+#include "cerise.h"
+
+void const_binop(int op, Item* a, Item* b)
+{
+    if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
+    {
+        switch (op)
+        {
+            case '+': a->imm.i = a->imm.i +  b->imm.i; break;
+            case '-': a->imm.i = a->imm.i -  b->imm.i; break;
+            case '*': a->imm.i = a->imm.i *  b->imm.i; break;
+            case '/': a->imm.i = a->imm.i /  b->imm.i; break;
+            case '%': a->imm.i = a->imm.i %  b->imm.i; break;
+            case AND: a->imm.i = a->imm.i && b->imm.i; break;
+            case OR:  a->imm.i = a->imm.i || b->imm.i; break;
+
+            case EQ:
+                a->imm.i = a->imm.i == b->imm.i;
+                a->type = &BoolType;
+                break;
+
+            case NEQ:
+                a->imm.i = a->imm.i != b->imm.i;
+                a->type = &BoolType;
+                break;
+
+            case '<':
+                a->imm.i = a->imm.i < b->imm.i;
+                a->type = &BoolType;
+                break;
+
+            case LTEQ:
+                a->imm.i = a->imm.i <= b->imm.i;
+                a->type = &BoolType;
+                break;
+
+            case '>':
+                a->imm.i = a->imm.i > b->imm.i;
+                a->type = &BoolType;
+                break;
+
+            case GTEQ:
+                a->imm.i = a->imm.i >= b->imm.i;
+                a->type = &BoolType;
+                break;
+
+//            case IS:    break;
+
+            default:
+                assert(!"not a valid op");
+                break;
+        }
+    }
+    else if (a->type->form == FORM_REAL)
+    {
+        switch (op)
+        {
+            case '+': a->imm.f = a->imm.f +  b->imm.f; break;
+            case '-': a->imm.f = a->imm.f -  b->imm.f; break;
+            case '*': a->imm.f = a->imm.f *  b->imm.f; break;
+            case '/': a->imm.f = a->imm.f /  b->imm.f; break;
+
+            case EQ:
+                a->imm.f = a->imm.f == b->imm.f;
+                a->type = &BoolType;
+                break;
+
+            case NEQ:
+                a->imm.f = a->imm.f != b->imm.f;
+                a->type = &BoolType;
+                break;
+
+            case '<':
+                a->imm.f = a->imm.f < b->imm.f;
+                a->type = &BoolType;
+                break;
+
+            case LTEQ:
+                a->imm.f = a->imm.f <= b->imm.f;
+                a->type = &BoolType;
+                break;
+
+            case '>':
+                a->imm.f = a->imm.f > b->imm.f;
+                a->type = &BoolType;
+                break;
+
+            case GTEQ:
+                a->imm.f = a->imm.f >= b->imm.f;
+                a->type = &BoolType;
+                break;
+
+            default:
+                assert(!"not a valid op");
+                break;
+        }
+    }
+    else
+    {
+        assert(!"not a valid form");
+    }
+}
+
+void const_unop(Parser* p, int op, Item* a)
+{
+    (void)p;
+    if (a->type->form == FORM_INT)
+    {
+        switch (op)
+        {
+            case '+': a->imm.i = +a->imm.i;      break;
+            case '-': a->imm.i = -a->imm.i;      break;
+            default:  assert(!"not a valid op"); break;
+        }
+    }
+    else if (a->type->form == FORM_REAL)
+    {
+        switch (op)
+        {
+            case '+': a->imm.f = +a->imm.f;      break;
+            case '-': a->imm.f = -a->imm.f;      break;
+            default:  assert(!"not a valid op"); break;
+        }
+    }
+    else if (a->type->form == FORM_BOOL)
+    {
+        switch (op)
+        {
+            case NOT: a->imm.i = !a->imm.i;      break;
+            default:  assert(!"not a valid op"); break;
+        }
+    }
+    else
+    {
+        assert(!"not a valid form");
+    }
+}
index de352730dfd99f46988b6240a7d6c2302a1d71de..f33cbfd2e2df9b1db20abaf91270fd28f0835e48 100644 (file)
@@ -18,7 +18,21 @@ begin
 #    a = A;
 #    b = 24;
 #    b = B;
+
+    # Immediate ops
     c = b + 1;
-    c = 1 + b;
+#    c = b - 1;
+#    c = b * 1;
+
+#    c = b == 1;
+
+    # Register ops
+#    c = 1 + b;
+#    c = 1 - b;
+#    c = 1 * b;
+
 #    c = b + b;
+
+    # Complex arithmetic
+#    c = b + b * b + b
 end
index 8ef8b9e28f29bf49be02a81b4797a8d9f1ae18b1..d39ed315d3836157dc7d91257f0b7bc995cc9193 100644 (file)
@@ -19,12 +19,7 @@ Module:
 
 //  c = ...
     movq    Module_b(%rip), %rdi
-    addq    $1, %rdi
-    movq    %rdi, Module_c(%rip)
-
-//  c = ...
-    movq    Module_b(%rip), %rdi
-    addq    $1, %rdi
+    addq   $1, %rdi
     movq    %rdi, Module_c(%rip)
 
     pop     %rbp