]> git.mdlowis.com Git - proto/obnc.git/commitdiff
added scaffolding to generate assembly code
authormike lowis <mike@mdlowis.com>
Thu, 22 Apr 2021 02:06:48 +0000 (22:06 -0400)
committermike lowis <mike@mdlowis.com>
Thu, 22 Apr 2021 02:06:48 +0000 (22:06 -0400)
cerise/build.sh
cerise/cerise.h
cerise/codegen.c
cerise/main.c
cerise/parser.c
cerise/tests/Module.m [new file with mode: 0644]

index ec4bcc0ad261791c128bfe94ad43b5ab0b87b7b7..6328d79d4f93d36d5de8a3f672b0ba3dd53888bd 100755 (executable)
@@ -1,6 +1,7 @@
 #!/bin/sh
 ctags -R &
 cc -g -D CERISE_TESTS -Wall -Wextra --std=c99 -o cerisec-test *.c \
-  && ./cerisec-test
-#  && cc -g -Wall -Wextra -Werror --std=c99 -o cerisec *.c
-[ $? -gt 0 ] && printf "\a"
+  && ./cerisec-test \
+  && cc -g -Wall -Wextra -Werror --std=c99 -o cerisec *.c \
+  && ./cerisec tests/Module.m
+#[ $? -gt 0 ] && printf "\a"
index 08df7ebb6dfed204a6acc007cc55211367f87a5b..84339aa8e61c2953d750216e2dcb5d1b90724baa 100644 (file)
@@ -125,11 +125,10 @@ typedef struct {
 void lexfile(Parser* ctx, char* path);
 void lex(Parser* ctx);
 void lexprintpos(Parser* p, FILE* file, Tok* tok);
-void module(Parser* p, Item* item);
+void compile(char* fname);
 
 /* Code Generation
  *****************************************************************************/
-
 extern Type BoolType, IntType, RealType, StringType;
 
 void codegen_setint(Item* item, Type* type, long long val);
@@ -137,84 +136,5 @@ 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_startproc(long long localsz);
+void codegen_startproc(char* name, long long localsz);
 void codegen_endproc(void);
-
-/* Option Parsing
- *****************************************************************************/
-
-/* This variable contains the value of argv[0] so that it can be referenced
- * again once the option parsing is done. This variable must be defined by the
- * program.
- *
- * NOTE: Ensure that you define this variable with external linkage (i.e. not
- * static)
- */
-extern char* ARGV0;
-
-/* This is a helper function used by the macros in this file to parse the next
- * option from the command line.
- */
-static inline char* __getopt(int* p_argc, char*** p_argv) {
-    if (!(*p_argv)[0][1] && !(*p_argv)[1]) {
-        return (char*)0;
-    } else if ((*p_argv)[0][1]) {
-        return &(*p_argv)[0][1];
-    } else {
-        *p_argv = *p_argv + 1;
-        *p_argc = *p_argc - 1;
-        return (*p_argv)[0];
-    }
-}
-
-/* This macro is almost identical to the ARGBEGIN macro from suckless.org. If
- * it ain't broke, don't fix it. */
-#define OPTBEGIN                                                              \
-    for (                                                                     \
-        ARGV0 = *argv, argc--, argv++;                                        \
-        argv[0] && argv[0][1] && argv[0][0] == '-';                           \
-        argc--, argv++                                                        \
-    ) {                                                                       \
-        int brk_; char argc_ , **argv_, *optarg_;                             \
-        if (argv[0][1] == '-' && !argv[0][2]) {                               \
-            argv++, argc--; break;                                            \
-        }                                                                     \
-        for (brk_=0, argv[0]++, argv_=argv; argv[0][0] && !brk_; argv[0]++) { \
-            if (argv_ != argv) break;                                         \
-            argc_ = argv[0][0];                                               \
-            switch (argc_)
-
-/* Terminate the option parsing. */
-#define OPTEND }}
-
-/* Get the current option chracter */
-#define OPTC() (argc_)
-
-/* Get an argument from the command line and return it as a string. If no
- * argument is available, this macro returns NULL */
-#define OPTARG() \
-    (optarg_ = __getopt(&argc,&argv), brk_ = (optarg_!=0), optarg_)
-
-/* Get an argument from the command line and return it as a string. If no
- * argument is available, this macro executes the provided code. If that code
- * returns, then abort is called. */
-#define EOPTARG(code) \
-    (optarg_ = __getopt(&argc,&argv), \
-     (!optarg_ ? ((code), abort(), (char*)0) : (brk_ = 1, optarg_)))
-
-/* Helper macro to recognize number options */
-#define OPTNUM \
-    case '0':  \
-    case '1':  \
-    case '2':  \
-    case '3':  \
-    case '4':  \
-    case '5':  \
-    case '6':  \
-    case '7':  \
-    case '8':  \
-    case '9'
-
-/* Helper macro to recognize "long" options ala GNU style. */
-#define OPTLONG \
-    case '-'
index 94d831907f2d84bf1f741d2d132096819591bc9b..860191386b2c8b4a2da6231bde058884214d26cd 100644 (file)
@@ -207,15 +207,21 @@ void codegen_binop(int op, Item* a, Item* b)
     }
 }
 
-void codegen_startproc(long long localsz)
+void codegen_startproc(char* name, long long localsz)
 {
-    printf("    pushq    rbp\n");
-    printf("    movq     rsp, rbp\n");
-    printf("    sub      $%lld, rsp\n", 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);
+    }
 }
 
 void codegen_endproc(void)
 {
-    printf("    pop      rbp");
-    printf("    ret");
+    printf("    pop      %%rbp\n");
+    printf("    ret\n");
 }
index cea9b8ff29fe7bea370400dc6974d93c9d0cc22d..22e00520b8931bfba803b2913a41451f97ddda88 100644 (file)
@@ -2,61 +2,14 @@
 
 #ifndef CERISE_TESTS
 
-char* ARGV0;
-char* Artifact = "bin";
-
-/* Driver Modes
- *****************************************************************************/
-static int emit_binary(Parser* ctx, int argc, char **argv)
-{
-    (void)ctx, (void)argc, (void)argv;
-    return 0;
-}
-
-static int emit_library(Parser* ctx, int argc, char **argv)
-{
-    (void)ctx, (void)argc, (void)argv;
-    return 0;
-}
-
-/* Main Routine and Usage
- *****************************************************************************/
-void usage(void)
-{
-    fprintf(stderr, "%s\n",
-        "Usage: sclpl [options...] [-A artifact] [file...]\n"
-        "\n-A<artifact> Emit the given type of artifact"
-        "\n-h           Print help information"
-    );
-    exit(1);
-}
-
 int main(int argc, char **argv)
 {
-    /* Option parsing */
-    OPTBEGIN {
-        case 'A': Artifact = EOPTARG(usage()); break;
-        default:  usage();
-    } OPTEND;
-    /* initialize the parser */
-    Parser ctx = {0};
-    for (; argc; argc--,argv++)
-        lexfile(&ctx, *argv);
-    /* Execute the main compiler process */
-    if (0 == strcmp("bin", Artifact))
-    {
-        return emit_binary(&ctx, argc, argv);
-    }
-    else if (0 == strcmp("lib", Artifact))
+    if (argc >= 2)
     {
-        return emit_library(&ctx, argc, argv);
+        compile( argv[1] );
     }
-    else
-    {
-        fprintf(stderr, "Unknown artifact type: '%s'\n\n", Artifact);
-        usage();
-    }
-    return 1;
+
+    return 0;
 }
 
 #else
index d3ca8f949b0ea4e2666757001264655a2c92635a..c91309e1ce65550915b581d7b705b69327322577 100644 (file)
@@ -1,5 +1,8 @@
 #include "cerise.h"
 #include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
 
 //#define TRACE
 #ifdef TRACE
@@ -413,7 +416,7 @@ RULE(var_decl)
     {
         name = expect_text(p, IDENT);
         export = accept(p, '*');
-        sym = symbol_new(p, name, SYM_CONST, export);
+        sym = symbol_new(p, name, SYM_VAR, export);
         nsyms++;
 
         if (!accept(p, ','))
@@ -471,12 +474,21 @@ RULE(const_decl)
 
 RULE(statement_seq)
 {
-    (void)item;
     if (matches(p, IDENT))
     {
+        char* text = expect_text(p, IDENT);
         if (accept(p, '='))
         {
-
+            Symbol* sym = symbol_get(p, text);
+            if (!sym)
+            {
+                error(p, "undefined variable '%s'", text);
+            }
+            else if (sym->class != SYM_VAR)
+            {
+                error(p, "assignment to non-variable '%s'", text);
+            }
+            expression(p, item);
         }
         else
         {
@@ -552,7 +564,7 @@ RULE(module)
 
     if (accept(p, BEGIN))
     {
-        codegen_startproc(0);
+        codegen_startproc("Module", 0);
         statement_seq(p, item);
         codegen_endproc();
     }
@@ -566,6 +578,51 @@ RULE(module)
     expect(p, ';');
 }
 
+static inline char* file_load(char* path) 
+{
+    int fd = -1, nread = 0, length = 0;
+    struct stat sb = {0};
+    char* contents = NULL;
+    if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0)) 
+    {
+        contents = calloc(sb.st_size + 1u, 1u);
+        while (sb.st_size && (nread = read(fd, contents+length, sb.st_size)) > 0)
+        {
+            length += nread, sb.st_size -= nread;
+        }
+    }
+    if (fd > 0) 
+    {
+        close(fd);
+    }
+    return contents;
+}
+
+void compile(char* fname)
+{
+    char* fcontents = file_load(fname);
+    module(
+        &(Parser){
+            .scope = &RealSym,
+            .file  = &(LexFile){
+                .path  = fname,
+                .fbeg  = fcontents,
+                .fpos  = fcontents,
+            }
+        }, 
+        &(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");
+}
+
 /* Grammar Unit Tests
  *****************************************************************************/
 #ifdef CERISE_TESTS
diff --git a/cerise/tests/Module.m b/cerise/tests/Module.m
new file mode 100644 (file)
index 0000000..7eefeac
--- /dev/null
@@ -0,0 +1,6 @@
+module Module;
+const FOO = 42;
+var a : Int;
+begin
+  a = FOO * 3;
+end Module;