]> git.mdlowis.com Git - proto/obnc.git/commitdiff
got primitive code generation working for assignments
authorMichael D. Lowis <mike.lowis@gentex.com>
Thu, 22 Apr 2021 20:12:28 +0000 (16:12 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Thu, 22 Apr 2021 20:12:28 +0000 (16:12 -0400)
cerise/build.sh
cerise/cerise.h
cerise/codegen.c
cerise/oberon0/OSG.Mod
cerise/parser.c
cerise/tests/Module.m
cerise/tests/Module.s [new file with mode: 0644]

index a6d65d1afd971ab64a645827a478ac637934daca..e0a3c86274bb38bd4637401dfdca7daf73839b7b 100755 (executable)
@@ -3,5 +3,7 @@ ctags -R &
 cc -g -D CERISE_TESTS -Wall -Wextra --std=c99 -o cerisec-test *.c \
   && ./cerisec-test \
   && cc -g -Wall -Wextra --std=c99 -o cerisec *.c \
-  && ./cerisec tests/Module.m
+  && ./cerisec tests/Module.m | tee tests/Module.s \
+  && cc -o Module tests/Module.s
+rm Module
 #[ $? -gt 0 ] && printf "\a"
index 5b6a02d4f6b82550dda61eed9048f0ab366939d8..98bfe079f0c95729e6c101cb105fec3667e40615 100644 (file)
@@ -112,6 +112,7 @@ typedef struct {
         ITEM_CONST, ITEM_VAR
     } mode;
     Type* type;
+    int reg;
     ImmValue imm;
 } Item;
 
@@ -129,14 +130,31 @@ void compile(char* fname);
 
 /* Code Generation
  *****************************************************************************/
+/* opcodes */
+enum AsmOp {
+    /* Assembly Operations */
+    OP_LOAD = 0, OP_STORE, OP_MOVE,
+    OP_CMP, OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD,
+    OP_EQ, OP_NEQ, OP_LT, OP_GT, OP_LTEQ, OP_GTEQ,
+
+    OP_CALL, OP_RET,
+};
+
+enum Regs {
+    IMM = 0,
+    RAX, RBX, RCX, RDX, RBP, RSP, RSI, RDI,
+    R8, R9, R10, R11, R12, R13, R14, R15,
+};
+
 extern Type BoolType, IntType, RealType, StringType;
 
 void codegen_setint(Item* item, Type* type, long long val);
 void codegen_setreal(Item* item, double val);
 void codegen_setstr(Item* item, char* val);
 
-void codegen_unop(int op, Item* a);
-void codegen_binop(int op, Item* a, Item* b);
+void codegen_main(char* modname);
 void codegen_startproc(char* name, long long localsz);
 void codegen_endproc(void);
+void codegen_unop(int op, Item* a);
+void codegen_binop(int op, Item* a, Item* b);
 void codegen_store(Item* a, Item* b);
index 5e2708f24088fcbdec6a70e46f81fa79176f11bd..08848eff86ae6669e9f28379f2b5fd51000268a5 100644 (file)
@@ -24,22 +24,25 @@ Type StringType = {
 
 void codegen_setint(Item* item, Type* type, long long val)
 {
-    item->mode = ITEM_CONST;
-    item->type = type;
+    item->mode  = ITEM_CONST;
+    item->type  = type;
+    item->reg   = IMM;
     item->imm.i = val;
 }
 
 void codegen_setreal(Item* item, double val)
 {
-    item->mode = ITEM_CONST;
-    item->type = &RealType;
+    item->mode  = ITEM_CONST;
+    item->type  = &RealType;
+    item->reg   = IMM;
     item->imm.f = val;
 }
 
 void codegen_setstr(Item* item, char* val)
 {
-    item->mode = ITEM_CONST;
-    item->type = &StringType;
+    item->mode  = ITEM_CONST;
+    item->type  = &StringType;
+    item->reg   = IMM;
     item->imm.s = val;
 }
 
@@ -183,6 +186,44 @@ static void const_unop(int op, Item* a)
     }
 }
 
+void codegen_main(char* modname)
+{
+    codegen_startproc("main", 0);
+//    op_l  (OP_CALL, modname);
+    printf("    call     %s\n", modname);
+    codegen_endproc();
+}
+
+void codegen_startproc(char* name, long long localsz)
+{
+    printf("    .text\n");
+    printf("    .globl %s\n", name);
+    printf("%s:\n", name);
+
+//    op_r  (OP_PUSH, RBP);
+    printf("    pushq    %%rbp\n");
+    if (localsz > 0)
+    {
+//    op_rr (OP_MOVE, RSP, RBP);
+    printf("    movq     %%rsp, %%rbp\n");
+//    op_ri (OP_SUB, localsz, RSP);
+        printf("    sub      $%lld, %%rsp\n\n", localsz);
+    }
+    else
+    {
+//        op_rr (OP_MOVE, RSP, RBP);
+        printf("    movq     %%rsp, %%rbp\n\n");
+    }
+}
+
+void codegen_endproc(void)
+{
+//    op_r  (OP_POP,  RBP);
+//    op_0  (OP_RET);
+    printf("\n    pop      %%rbp\n");
+    printf("    ret\n\n");
+}
+
 void codegen_unop(int op, Item* a)
 {
     if (a->mode == ITEM_CONST)
@@ -207,26 +248,134 @@ void codegen_binop(int op, Item* a, Item* b)
     }
 }
 
-void codegen_startproc(char* name, long long localsz)
-{
-    printf("    .text\n");
-    printf("    .globl %s\n", name);
-    printf("%s:\n", name);
-    printf("    pushq    %%rbp\n");
-    printf("    movq     %%rsp, %%rbp\n");
-    if (localsz > 0)
-    {
-        printf("    sub      $%lld, %%rsp\n", localsz);
-    }
-}
+/*
+  PROCEDURE GetSB;
+  BEGIN
+    IF curSB = 1 THEN
+      Put2(Ldw, SB, 0, pc-fixorgD);
+      fixorgD := pc-1;
+      curSB := 0
+    END
+  END GetSB;
 
-void codegen_endproc(void)
-{
-    printf("    pop      %%rbp\n");
-    printf("    ret\n");
-}
+  PROCEDURE load(VAR x: Item);
+  BEGIN
+    IF x.mode # Reg THEN
+      IF x.mode = Var THEN
+        IF x.r > 0 THEN (*local*)
+          Put2(Ldw, RH, SP, x.a)
+        ELSE
+          GetSB;
+          Put2(Ldw, RH, SB, x.a)
+        END ;
+        x.r := RH;
+        incR
+      ELSIF x.mode = Par THEN
+        Put2(Ldw, RH, x.r, x.a);
+        Put2(Ldw, RH, RH, 0);
+        x.r := RH;
+        incR
+      ELSIF x.mode = Const THEN
+        IF (x.a >= 10000H) OR (x.a < -10000H) THEN
+          OSS.Mark("const too large")
+        END ;
+        Put1(Mov, RH, 0, x.a);
+        x.r := RH;
+        incR
+      ELSIF x.mode = RegI THEN
+        Put2(Ldw, x.r, x.r, x.a)
+      ELSIF x.mode = Cond THEN
+        Put3(2, negated(x.r), 2);
+        FixLink(x.b);
+        Put1(Mov, RH, 0, 1);
+        Put3(2, 7, 1);
+        FixLink(x.a);
+        Put1(Mov, RH, 0, 0);
+        x.r := RH;
+        incR
+      END ;
+      x.mode := Reg
+    END
+  END load;
+
+  PROCEDURE Store*(VAR x, y: Item); (* x := y *)
+  BEGIN
+    load(y);
+    IF x.mode = Var THEN
+      IF x.r > 0 THEN (*local*)
+        Put2(Stw, y.r, SP, x.a)
+      ELSE
+        GetSB;
+        Put2(Stw, y.r, SB, x.a)
+      END
+    ELSIF x.mode = Par THEN
+        Put2(Ldw, RH, SP, x.a);
+        Put2(Stw, y.r, RH, x.b)
+    ELSIF x.mode = RegI THEN
+        Put2(Stw, y.r, x.r, x.a);
+        DEC(RH)
+    ELSE
+        OSS.Mark("illegal assignment")
+    END ;
+    DEC(RH)
+  END Store;
+
+*/
 
 void codegen_store(Item* a, Item* b)
 {
+    if (a->mode == ITEM_VAR && b->reg == IMM)
+    {
+        printf("    movq    $%lld, %s(%%rip)\n", b->imm.i, a->imm.s);
+    }
     (void)a, (void)b;
 }
+
+
+/*
+
+add %r10,%r11    // add r10 and r11, put result in r11
+add $5,%r10      // add 5 to r10, put result in r10
+call label       // call a subroutine / function / procedure
+cmp %r10,%r11    // compare register r10 with register r11.  The comparison sets flags in the processor status register which affect conditional jumps.
+cmp $99,%r11     // compare the number 99 with register r11.  The comparison sets flags in the processor status register which affect conditional jumps.
+div %r10         // divide rax by the given register (r10), places quotient into rax and remainder into rdx (rdx must be zero before this instruction)
+inc %r10         // increment r10
+jmp label        // jump to label
+je  label        // jump to label if equal
+jne label        // jump to label if not equal
+jl  label        // jump to label if less
+jg  label        // jump to label if greater
+mov %r10,%r11    // move data from r10 to r11
+mov $99,%r10     // put the immediate value 99 into r10
+mov %r10,(%r11)  // move data from r10 to address pointed to by r11
+mov (%r10),%r11  // move data from address pointed to by r10 to r10
+mul %r10         // multiplies rax by r10, places result in rax and overflow in rdx
+push %r10        // push r10 onto the stack
+pop %r10         // pop r10 off the stack
+ret              // routine from subroutine (counterpart to call)
+syscall          // invoke a syscall (in 32-bit mode, use "int $0x80" instead)
+
+*/
+
+//static void emit_op0(AsmOp op)
+//{
+//}
+//
+//static void emit_opreg1(AsmOp op, long long reg)
+//{
+//}
+//
+//static void emit_opimmi(AsmOp op, long long imm)
+//{
+//}
+//
+//static void emit_opimmf(AsmOp op, double imm)
+//{
+//}
+//
+//static void emit_opreg2(AsmOp op, int rega, int regb)
+//{
+//}
+
+
index 29e87532aa6463816beba01c4dceecd0d880fb0f..9e4b750291e1f9d6c87a796bdef42c9b0466359f 100644 (file)
@@ -331,7 +331,8 @@ MODULE OSG; (* NW 19.12.94 / 20.10.07 / OSGX  9.5.2017*)
   END Relation;\r
 \r
   PROCEDURE Store*(VAR x, y: Item); (* x := y *)\r
-  BEGIN load(y);\r
+  BEGIN\r
+    load(y);\r
     IF x.mode = Var THEN\r
       IF x.r > 0 THEN (*local*) Put2(Stw, y.r, SP, x.a) ELSE GetSB; Put2(Stw, y.r, SB, x.a) END\r
     ELSIF x.mode = Par THEN Put2(Ldw, RH, SP, x.a); Put2(Stw, y.r, RH, x.b)\r
index 5a5e20c690bd4b064a7f1d763c9ff4b5538bd206..c315d8d5f57e4f7a14f024a875de21a74967765e 100644 (file)
@@ -247,6 +247,10 @@ static void check_types(Parser* p, Item* a, Item* b)
     {
         check_ints(p, a, b);
     }
+    else if (a->type->form == FORM_BOOL)
+    {
+        check_bools(p, a, b);
+    }
     else
     {
         error(p, "type mismatch");
@@ -447,35 +451,43 @@ RULE(expression)
 RULE(var_decl)
 {
     (void)item;
-    int nsyms = 0;
-    Symbol* sym = NULL;
-    Symbol* type = NULL;
-    char* name = NULL;
-    bool export = false;
-
     while (1)
     {
+        int nsyms = 0;
+        Symbol* sym = NULL;
+        Symbol* type = NULL;
+        char* name = NULL;
+        bool export = false;
+
+        while (1)
+        {
+            name = expect_text(p, IDENT);
+            export = accept(p, '*');
+            sym = symbol_new(p, name, SYM_VAR, export);
+            nsyms++;
+
+            if (!accept(p, ','))
+            {
+                break;
+            }
+        }
+
+        expect(p, ':');
         name = expect_text(p, IDENT);
-        export = accept(p, '*');
-        sym = symbol_new(p, name, SYM_VAR, export);
-        nsyms++;
+        type = symbol_get(p, SYM_TYPE, name);
+
+        /* apply the type to the newly created symbols */
+        for (int i = 0; i < nsyms; i++)
+        {
+            sym->type = type->type;
+            sym = sym->next;
+        }
 
         if (!accept(p, ','))
         {
             break;
         }
     }
-
-    expect(p, ':');
-    name = expect_text(p, IDENT);
-    type = symbol_get(p, SYM_TYPE, name);
-
-    /* apply the type to the newly created symbols */
-    for (int i = 0; i < nsyms; i++)
-    {
-        sym->type = type->type;
-        sym = sym->next;
-    }
 }
 
 RULE(type_decl)
@@ -558,32 +570,41 @@ END
 
 RULE(statement_seq)
 {
-    if (matches(p, IDENT))
+    while (1)
     {
-        Item right = { 0 };
-        char* text = expect_text(p, IDENT);
-        if (accept(p, '='))
+        if (matches(p, IDENT))
+        {
+            Item right = { 0 };
+            char* text = expect_text(p, IDENT);
+            if (accept(p, '='))
+            {
+                Symbol* sym = symbol_get(p, SYM_VAR, text);
+                init_item(item, sym);
+                item->imm.s = sym->name;
+
+                expression(p, &right);
+                check_types(p, item, &right);
+                codegen_store(item, &right);
+            }
+            else
+            {
+                /* TODO: add function calls and other complex stuff */
+                error(p, "expected assignment");
+            }
+        }
+        else if (matches(p, IF))
         {
-            Symbol* sym = symbol_get(p, SYM_VAR, text);
-            init_item(item, sym);
-            expression(p, &right);
-            check_types(p, item, &right);
-            codegen_store(item, &right);
         }
         else
         {
-            /* TODO: add function calls and other complex stuff */
-            error(p, "expected assignment");
+            error(p, "expected a statement");
+        }
+        expect(p, ';');
+        if (matches_oneof(p, (int[]){END, 0}))
+        {
+            break;
         }
     }
-    else if (matches(p, IF))
-    {
-    }
-    else
-    {
-        error(p, "expected a statement");
-    }
-    expect(p, ';');
 }
 
 RULE(declaration_seq)
@@ -693,15 +714,7 @@ void compile(char* fname)
         },
         &(Item){0}
     );
-
-    printf("    .text\n");
-    printf("    .globl main\n");
-    printf("main:\n");
-    printf("    pushq    %%rbp\n");
-    printf("    movq     %%rsp, %%rbp\n");
-    printf("    call     Module\n");
-    printf("    pop      %%rbp\n");
-    printf("    ret\n");
+    codegen_main("Module");
 }
 
 /* Grammar Unit Tests
index 7eefeac86281ce7a5cf567bc1801ee1ea678e230..1b9e81169613091e8c728c8b2410865be57bb9bc 100644 (file)
@@ -1,6 +1,19 @@
 module Module;
-const FOO = 42;
-var a : Int;
+
+const
+    A = true,
+    B = 42
+    ;
+
+var
+    a : Bool,
+    b : Int
+    ;
+
 begin
-  a = FOO * 3;
+  a = true;
+  a = A;
+  b = 24;
+  b = B;
+#  c = a + b;
 end Module;
diff --git a/cerise/tests/Module.s b/cerise/tests/Module.s
new file mode 100644 (file)
index 0000000..91f16b4
--- /dev/null
@@ -0,0 +1,25 @@
+    .text
+    .globl Module
+Module:
+    pushq    %rbp
+    movq     %rsp, %rbp
+
+    movq    $1, a(%rip)
+    movq    $1, a(%rip)
+    movq    $24, b(%rip)
+    movq    $42, b(%rip)
+
+    pop      %rbp
+    ret
+
+    .text
+    .globl main
+main:
+    pushq    %rbp
+    movq     %rsp, %rbp
+
+    call     Module
+
+    pop      %rbp
+    ret
+