Procedure compilation now happens after the entire EM file has been read in (so
authorDavid Given <dg@cowlark.com>
Fri, 23 Sep 2016 23:04:00 +0000 (01:04 +0200)
committerDavid Given <dg@cowlark.com>
Fri, 23 Sep 2016 23:04:00 +0000 (01:04 +0200)
that we can look inside data blocks which might be defined in the future...
sigh, csa and csb). csa and csb no longer generate invalid IR.

mach/proto/mcg/main.c
mach/proto/mcg/mcg.h
mach/proto/mcg/parse_em.c
mach/proto/mcg/pass_eliminatetrivialblocks.c
mach/proto/mcg/procedure.c [moved from mach/proto/mcg/compile.c with 79% similarity]
mach/proto/mcg/symbol.c
mach/proto/mcg/treebuilder.c

index 6c9a280..5be59e6 100644 (file)
@@ -39,7 +39,7 @@ bool tracing(char k)
     {
         case 'E': return false;
         case '0': return false;
-        case '1': return false;
+        case '1': return true;
         case '2': return true;
         default:  return true;
     }
@@ -57,6 +57,13 @@ void tracef(char k, const char* fmt, ...)
     }
 }
 
+static bool find_procedures_cb(struct symbol* symbol, void* user)
+{
+    if (symbol->proc)
+        procedure_compile(symbol->proc);
+    return false;
+}
+
 int main(int argc, char* argv[])
 {
     symbol_init();
@@ -64,8 +71,17 @@ int main(int argc, char* argv[])
        if (!EM_open(argv[1]))
                fatal("Couldn't open input file: %s", EM_error);
        
+    /* Reads in the EM, outputs the data sections, parses any code and
+     * generates IR trees. */
+
     parse_em();
 
+    /* For every procedure, go ahead and do the compilation proper. We do this
+     * now so that we know that all the data has been read correctly and our
+     * symbol table is complete (we may need to refer to it). */
+
+    symbol_walk(find_procedures_cb, NULL);
+
        EM_close();
        return 0;
 }
index a7b8d68..4fa1b11 100644 (file)
@@ -36,6 +36,7 @@ struct symbol
 {
        const char* name;
        int section;
+    struct procedure* proc;
        bool is_defined : 1;
        bool is_exported : 1;
        bool is_proc : 1;
@@ -96,6 +97,9 @@ extern bool symbol_exists(const char* name);
 extern struct symbol* symbol_get(const char* name);
 extern void symbol_declare(const char* name, bool is_exported, bool is_proc);
 
+typedef bool symbol_walker_t(struct symbol* symbol, void* user);
+extern struct symbol* symbol_walk(symbol_walker_t* walker, void* user);
+
 extern void data_label(const char* name);
 extern void data_int(arith data, size_t size, bool is_ro);
 extern void data_block(const uint8_t* data, size_t size, bool is_ro);
@@ -116,7 +120,7 @@ extern void pass_convert_stack_ops(struct procedure* proc);
 extern void pass_remove_dead_blocks(struct procedure* proc);
 extern void pass_eliminate_trivial_blocks(struct procedure* proc);
 
-extern void compile(struct procedure* proc);
+extern void procedure_compile(struct procedure* proc);
 
 #endif
 
index 7daecfe..699e6b4 100644 (file)
@@ -280,6 +280,9 @@ static void parse_pseu(void)
         }
 
                case ps_pro: /* procedure start */
+        {
+            struct symbol* symbol;
+
             current_proc = calloc(sizeof(struct procedure), 1);
             current_proc->name = strdup(insn.em_pnam);
             current_proc->root_bb = bb_get(current_proc->name);
@@ -287,11 +290,16 @@ static void parse_pseu(void)
             code_bb = current_proc->root_bb;
             code_bb->is_root = true;
             APPEND(current_proc->blocks, code_bb);
+
+            symbol = symbol_get(current_proc->name);
+            symbol->section = SECTION_TEXT;
+            symbol->proc = current_proc;
+            symbol->is_proc = true;
             break;
+        }
 
                case ps_end: /* procedure end */
             tb_procedure(current_proc);
-            compile(current_proc);
 
             current_proc = NULL;
             code_bb = NULL;
@@ -336,6 +344,17 @@ static void parse_mes(void)
         fatal("malformed MES");
 }
 
+static void create_data_label(const char* label)
+{
+    data_label(label);
+    if (current_proc)
+    {
+        data_bb = bb_get(label);
+        data_bb->is_fake = true;
+        APPEND(current_proc->blocks, data_bb);
+    }
+}
+
 void parse_em(void)
 {
     EM_getinstr(&insn);
@@ -354,16 +373,11 @@ void parse_em(void)
                 break;
 
             case EM_DEFDLB:
-            {
-                const char* label = dlabel_to_str(insn.em_dlb);
-                data_label(label);
-                data_bb = bb_get(label);
-                data_bb->is_fake = true;
+                create_data_label(dlabel_to_str(insn.em_dlb));
                 break;
-            }
 
             case EM_DEFDNAM:
-                data_label(strdup(insn.em_dnam));
+                create_data_label(strdup(insn.em_dnam));
                 break;
 
             case EM_STARTMES:
index 96c8e08..3b72804 100644 (file)
@@ -5,7 +5,8 @@ static bool rewrite_jumps_cb(struct ir* ir, void* user)
     if (ir->opcode == IR_BLOCK)
     {
         struct basicblock* bb = ir->u.bvalue;
-        if ((bb->irs_count > 0)
+               if (!bb->is_fake
+                       && (bb->irs_count > 0)
             && (bb->irs[0]->opcode == IR_JUMP)
             && (bb->irs[0]->left->opcode == IR_BLOCK))
         {
similarity index 79%
rename from mach/proto/mcg/compile.c
rename to mach/proto/mcg/procedure.c
index c6fea43..8958a8b 100644 (file)
@@ -11,14 +11,16 @@ static void print_blocks(char k, struct procedure* proc)
                int j;
 
         tracef(k, "%c:\n", k);
-               tracef(k, "%c: BLOCK: %s\n", k, bb->name);
+               tracef(k, "%c: %sBLOCK: %s\n", k,
+            bb->is_fake ? "FAKE " : "",
+            bb->name);
 
                for (int j=0; j<bb->irs_count; j++)
                        ir_print(k, bb->irs[j]);
        }
 }
 
-void compile(struct procedure* proc)
+void procedure_compile(struct procedure* proc)
 {
        int i;
 
index 14ec4a9..f8c2f52 100644 (file)
@@ -1,7 +1,10 @@
 #include "mcg.h"
 
+typedef int idf_walker_t(struct idf* idf, void* user);
+
 static void init_idf();
 static struct idf* str2idf(char* tg, int cp);
+static struct idf* walk_idf(idf_walker_t* cb, void* user);
 
 #define IDF_TYPE struct symbol
 #define IDF_NAME symbol
@@ -39,3 +42,22 @@ void symbol_declare(const char* name, bool is_exported, bool is_proc)
        }
 }
 
+struct symbol* symbol_walk(symbol_walker_t* cb, void* user)
+{
+       int i;
+
+       for (i=0; i<IDF_HASHSIZE; i++)
+       {
+               struct idf* idf = IDF_hashtable[i];
+               while (idf)
+               {       
+                       struct symbol* symbol = &idf->symbol;
+                       if (cb(symbol, user))
+                               return &symbol;
+                       idf = idf->id_next;
+               }
+       }
+
+       return NULL;
+}
+
index 39d529f..ea699d7 100644 (file)
@@ -281,6 +281,12 @@ static void insn_bvalue(int opcode, struct basicblock* leftbb, struct basicblock
             break;
         }
 
+        case op_lae:
+            push(
+                new_bbir(leftbb)
+            );
+            break;
+
         default:
             fatal("treebuilder: unknown bvalue instruction '%s'",
                 em_mnem[opcode - sp_fmnem]);
@@ -312,6 +318,27 @@ static void simple_alu2(int opcode, int size, int irop)
     );
 }
 
+static struct ir* extract_block_refs(struct basicblock* bb)
+{
+    struct ir* outir = NULL;
+    int i;
+
+    for (i=0; i<bb->insns_count; i++)
+    {
+        struct insn* insn = bb->insns[i];
+        assert(insn->opcode == op_bra);
+        assert(insn->paramtype == PARAM_BVALUE);
+
+        outir = new_ir2(
+            IR_PAIR, 0,
+            new_bbir(insn->u.bvalue.left),
+            outir
+        );
+    }
+
+    return outir;
+}
+
 static void insn_ivalue(int opcode, arith value)
 {
     switch (opcode)
@@ -540,17 +567,13 @@ static void insn_ivalue(int opcode, arith value)
                 fatal("csa/csb are only supported if they refer "
                     "directly to a descriptor block");
 
-            /* Turn the label reference into a block. */
-
-            descriptor->opcode = IR_BLOCK;
-            descriptor->u.bvalue = bb_get(descriptor->u.lvalue);
-
             push(descriptor);
             materialise_stack();
             appendir(
-                new_ir1(
+                new_ir2(
                     IR_JUMP, 0,
-                    new_labelir(helper)
+                    new_labelir(helper),
+                    extract_block_refs(bb_get(descriptor->u.lvalue))
                 )
             );
             break;
@@ -675,6 +698,7 @@ void tb_procedure(struct procedure* current_proc)
 
     for (i=0; i<current_proc->blocks_count; i++)
         generate_tree(current_proc->blocks[i]);
+
 }
 
 /* vim: set sw=4 ts=4 expandtab : */