Function termination gets routed through an exit block; we now have prologues
authorDavid Given <dg@cowlark.com>
Sat, 15 Oct 2016 16:38:46 +0000 (18:38 +0200)
committerDavid Given <dg@cowlark.com>
Sat, 15 Oct 2016 16:38:46 +0000 (18:38 +0200)
and epilogues. mcgg now exports some useful data as headers. Start factoring
out some of the architecture-specific bits into an architecture-specific file.

20 files changed:
mach/proto/mcg/build.lua
mach/proto/mcg/hop.c
mach/proto/mcg/hop.h
mach/proto/mcg/mcg.h
mach/proto/mcg/mcgg_generated_header.h
mach/proto/mcg/parse_em.c
mach/proto/mcg/pass_instructionselection.c
mach/proto/mcg/pass_prologueepilogue.c [new file with mode: 0644]
mach/proto/mcg/pass_registerallocator.c
mach/proto/mcg/powerpc.c [new file with mode: 0644]
mach/proto/mcg/procedure.c
mach/proto/mcg/procedure.h
mach/proto/mcg/reg.c
mach/proto/mcg/reg.h
mach/proto/mcg/table
mach/proto/mcg/treebuilder.c
util/mcgg/build.lua
util/mcgg/gram.y
util/mcgg/iburg.c
util/mcgg/iburg.h

index 0626c4a..8fc41be 100644 (file)
@@ -9,10 +9,11 @@ cprogram {
        name = "mcg",
        srcs = {
                "./*.c",
-               "+mcgg_c",
+               matching(filenamesof("+mcgg_c"), "%.c$"),
        },
        deps = {
-               "util/mcgg+lib",
+               "+mcgg_c",
+               "./*.h",
                "h+emheaders",
                "modules+headers",
                "modules/src/alloc+lib",
@@ -23,7 +24,7 @@ cprogram {
                "modules/src/read_em+lib_ev",
                "modules/src/string+lib",
                "modules/src/system+lib",
-               "./*.h",
+               "util/mcgg+lib",
        },
        vars = {
                ["+cflags"] = {
index a362f8b..3797d7b 100644 (file)
@@ -58,6 +58,55 @@ void hop_add_eoi_insel(struct hop* hop)
        array_append(&hop->insels, insel);
 }
 
+void hop_add_insel(struct hop* hop, const char* fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+
+    while (*fmt)
+    {
+        if (*fmt == '%')
+        {
+            fmt += 2;
+            switch (fmt[-1])
+            {
+                case 'd':
+                    hop_add_string_insel(hop, aprintf("%d", va_arg(ap, int)));
+                    break;
+
+                case 'H':
+                    hop_add_hreg_insel(hop, va_arg(ap, struct hreg*));
+                    break;
+
+                case 'V':
+                    hop_add_vreg_insel(hop, va_arg(ap, struct vreg*));
+                    break;
+            }
+        }
+        else
+        {
+            const char* end = strchr(fmt, '%');
+            const char* s;
+            if (end)
+            {
+                int len = end - fmt;
+                s = strndup(fmt, len);
+                fmt = end;
+            }
+            else
+            {
+                s = fmt;
+                fmt += strlen(fmt);
+            }
+
+            hop_add_string_insel(hop, s);
+        }
+    }
+
+    hop_add_eoi_insel(hop);
+    va_end(ap);
+}
+
 static void print_header(char k, struct hop* hop)
 {
     int i;
index 1dbf577..dcc6fe0 100644 (file)
@@ -55,6 +55,8 @@ extern void hop_add_vreg_insel(struct hop* hop, struct vreg* vreg);
 extern void hop_add_value_insel(struct hop* hop, struct ir* ir);
 extern void hop_add_eoi_insel(struct hop* hop);
 
+extern void hop_add_insel(struct hop* hop, const char* fmt, ...);
+
 extern char* hop_render(struct hop* hop);
 extern void hop_print(char k, struct hop* hop);
 
index 0df947d..5cd875e 100644 (file)
@@ -28,6 +28,7 @@
 #include "basicblock.h"
 #include "procedure.h"
 #include "graph.h"
+#include "tables.h"
 
 extern char em_pseu[][4];
 extern char em_mnem[][4];
@@ -109,12 +110,17 @@ extern void pass_group_irs(struct procedure* proc);
 extern void pass_insert_moves(void);
 extern void pass_instruction_selector(void);
 extern void pass_live_vreg_analysis(void);
+extern void pass_add_prologue_epilogue(struct procedure* proc);
 extern void pass_promote_float_ops(struct procedure* proc);
 extern void pass_register_allocator(void);
 extern void pass_remove_dead_blocks(struct procedure* proc);
 extern void pass_remove_dead_phis(void);
 extern void pass_split_critical_edges(struct procedure* proc);
 
+extern struct hop* platform_prologue(struct procedure* proc);
+extern struct hop* platform_epilogue(struct procedure* proc);
+extern struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest);
+
 extern FILE* outputfile;
 extern FILE* dominance_dot_file;
 extern FILE* cfg_dot_file;
index 5d9b3ae..f0bfa99 100644 (file)
@@ -1,7 +1,6 @@
 #include "mcg.h"
 #include "mcgg.h"
 
-
 #define PANIC printf
 
 #define burm_assert(b, s) assert(b)
index 27e3a8d..2b88eac 100644 (file)
@@ -307,9 +307,9 @@ static void parse_pseu(void)
 
             current_proc = calloc(sizeof(struct procedure), 1);
             current_proc->name = strdup(em.em_pnam);
-            current_proc->root_bb = bb_get(current_proc->name);
+            current_proc->entry = bb_get(current_proc->name);
             current_proc->nlocals = em.em_nlocals;
-            code_bb = current_proc->root_bb;
+            code_bb = current_proc->entry;
             code_bb->is_root = true;
             array_append(&current_proc->blocks, code_bb);
 
index 9b5a615..752648d 100644 (file)
@@ -205,7 +205,7 @@ static struct insn* walk_instructions(struct burm_node* node, int goal)
             hop_print('I', current_hop);
             array_append(&current_bb->hops, current_hop);
 
-            if (goal != 1)
+            if (goal != burm_stmt_NT)
                 insn->ir->result = insn->hop->output;
         }
     }
@@ -276,7 +276,7 @@ static void select_instructions(void)
             if (!insnno)
                 burm_panic_cannot_match(shadow);
 
-            walk_instructions(shadow, 1);
+            walk_instructions(shadow, burm_stmt_NT);
         }
        }
 }
diff --git a/mach/proto/mcg/pass_prologueepilogue.c b/mach/proto/mcg/pass_prologueepilogue.c
new file mode 100644 (file)
index 0000000..0566307
--- /dev/null
@@ -0,0 +1,19 @@
+#include "mcg.h"
+
+void pass_add_prologue_epilogue(struct procedure* proc)
+{
+       struct hop* prologue = platform_prologue(proc);
+       array_insert(&proc->entry->hops, prologue, 0);
+
+       if (proc->exit)
+       {
+               struct hop* epilogue = platform_epilogue(proc);
+
+               proc->exit->hops.count = 0;
+               array_append(&proc->exit->hops, epilogue);
+       }
+}
+
+/* vim: set sw=4 ts=4 expandtab : */
+
+
index fffc6a1..f967e31 100644 (file)
@@ -488,19 +488,6 @@ static void assign_hregs_to_vregs(void)
     }
 }
 
-static struct hop* create_move(struct basicblock* bb, struct hreg* src, struct hreg* dest)
-{
-    struct hop* hop = new_hop(bb, NULL);
-
-    hop_add_string_insel(hop, "! move ");
-    hop_add_hreg_insel(hop, src);
-    hop_add_string_insel(hop, " -> ");
-    hop_add_hreg_insel(hop, dest);
-    hop_add_eoi_insel(hop);
-
-    return hop;
-}
-
 static struct hop* create_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest)
 {
     struct hop* hop = new_hop(bb, NULL);
@@ -558,7 +545,7 @@ static int insert_moves(struct basicblock* bb, int index,
         {
             /* Copy. */
 
-            hop = create_move(bb, src, dest);
+            hop = platform_move(bb, src, dest);
             pmap_remove(&copies, src, dest);
         }
         else
@@ -567,7 +554,7 @@ static int insert_moves(struct basicblock* bb, int index,
 
             src = copies.item[0].left;
             dest = pmap_findleft(&copies, src);
-            hop = create_move(bb, src, dest);
+            hop = create_swap(bb, src, dest);
             pmap_remove(&copies, src, dest);
             pmap_remove(&copies, dest, src);
         }
diff --git a/mach/proto/mcg/powerpc.c b/mach/proto/mcg/powerpc.c
new file mode 100644 (file)
index 0000000..b5c6061
--- /dev/null
@@ -0,0 +1,41 @@
+#include "mcg.h"
+
+struct hop* platform_prologue(struct procedure* proc)
+{
+       int framesize = proc->nlocals + 8;
+       int retbase = proc->nlocals;
+
+       struct hop* hop = new_hop(proc->entry, NULL);
+
+       hop_add_insel(hop, "addi sp, fp, %d", -framesize);
+       hop_add_insel(hop, "mfspr 0, lr");
+       hop_add_insel(hop, "stw fp, %d(sp)", retbase);
+       hop_add_insel(hop, "stw 0, %d(sp)", retbase+4);
+       hop_add_insel(hop, "addi fp, sp, retbase");
+
+       return hop;
+}
+
+struct hop* platform_epilogue(struct procedure* proc)
+{
+       struct hop* hop = new_hop(proc->exit, NULL);
+
+       hop_add_insel(hop, "b .ret");
+
+       return hop;
+}
+
+struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest)
+{
+    struct hop* hop = new_hop(bb, NULL);
+
+       if ((src->type & burm_int_ATTR) && (dest->type & burm_int_ATTR))
+               hop_add_insel(hop, "mr %H, %H", dest, src);
+       else
+               fatal("cannot generate move from %s to %s", src->name, dest->name);
+
+    return hop;
+}
+
+/* vim: set sw=4 ts=4 expandtab : */
+
index af05f80..d6382b0 100644 (file)
@@ -190,6 +190,7 @@ void procedure_compile(struct procedure* proc)
     pass_live_vreg_analysis();
     print_hops('8', proc);
     pass_register_allocator();
+    pass_add_prologue_epilogue(proc);
     print_hops('9', proc);
 
     emit_procedure(proc);
index 2414db0..9d653b3 100644 (file)
@@ -11,7 +11,8 @@ struct local
 struct procedure
 {
     const char* name;
-    struct basicblock* root_bb;
+    struct basicblock* entry;
+    struct basicblock* exit;
     size_t nlocals;
     ARRAYOF(struct basicblock) blocks;
     IMAPOF(struct local) locals;
index bb72665..2cb5237 100644 (file)
@@ -14,17 +14,19 @@ struct hreg* new_hreg(const struct burm_register_data* brd)
        struct hreg* hreg = calloc(1, sizeof *hreg);
        hreg->name = brd->name;
     hreg->realname = brd->realname;
+    hreg->type = brd->type;
        hreg->attrs = brd->attrs;
        hreg->is_stacked = false;
        return hreg;
 }
 
-struct hreg* new_stacked_hreg(int offset, uint32_t attrs)
+struct hreg* new_stacked_hreg(int offset, uint32_t type)
 {
        struct hreg* hreg = calloc(1, sizeof *hreg);
        hreg->name = aprintf("stacked_%d", offset);
     hreg->realname = hreg->name;
-       hreg->attrs = attrs;
+    hreg->type = type;
+       hreg->attrs = type;
        hreg->is_stacked = true;
        hreg->offset = offset;
        return hreg;
index f1b5e1b..0f47dfd 100644 (file)
@@ -34,7 +34,7 @@ typedef PMAPOF(struct hreg, struct vreg) register_assignment_t;
 extern struct vreg* new_vreg(void);
 
 extern struct hreg* new_hreg(const struct burm_register_data* brd);
-extern struct hreg* new_stacked_hreg(int offset, uint32_t attrs);
+extern struct hreg* new_stacked_hreg(int offset, uint32_t type);
 
 #endif
 
index 6a24d9e..24b9d6e 100644 (file)
@@ -7,69 +7,69 @@ REGISTERS
      * a register into another register (e.g. for eviction).
      */
 
-    r12 "12" bytes4! int! volatile; 
-    r11 "11" bytes4! int! volatile; 
-    r10 "10" bytes4! int! volatile; 
-    r9  "9"  bytes4! int! volatile;
-    r8  "8"  bytes4! int! volatile;
-    r7  "7"  bytes4! int! volatile;
-    r6  "6"  bytes4! int! volatile;
-    r5  "5"  bytes4! int! volatile;
-    r4  "4"  bytes4! int! volatile;
-    r3  "3"  bytes4! int! ret volatile;
-
-    r31 "31" bytes4! int!; 
-    r30 "30" bytes4! int!; 
-    r29 "29" bytes4! int!; 
-    r28 "28" bytes4! int!; 
-    r27 "27" bytes4! int!; 
-    r26 "26" bytes4! int!; 
-    r25 "25" bytes4! int!; 
-    r24 "24" bytes4! int!; 
-    r23 "23" bytes4! int!; 
-    r22 "22" bytes4! int!; 
-    r21 "21" bytes4! int!; 
-    r20 "20" bytes4! int!; 
-    r19 "19" bytes4! int!; 
-    r18 "18" bytes4! int!; 
-    r17 "17" bytes4! int!; 
-    r16 "16" bytes4! int!;
-    r15 "15" bytes4! int!;
-    r14 "14" bytes4! int!;
-
-    f14 "14" bytes4! float! volatile;
-    f13 "13" bytes4! float! volatile;
-    f12 "12" bytes4! float! volatile;
-    f11 "11" bytes4! float! volatile;
-    f10 "10" bytes4! float! volatile;
-    f9  "9"  bytes4! float! volatile;
-    f8  "8"  bytes4! float! volatile;
-    f7  "7"  bytes4! float! volatile;
-    f6  "6"  bytes4! float! volatile;
-    f5  "5"  bytes4! float! volatile;
-    f4  "4"  bytes4! float! volatile;
-    f3  "3"  bytes4! float! volatile;
-    f2  "2"  bytes4! float! volatile;
-    f1  "1"  bytes4! float! volatile;
-    f0  "0"  bytes4! float! volatile;
-
-    f31 "31" bytes4! float!;
-    f30 "30" bytes4! float!;
-    f29 "29" bytes4! float!;
-    f28 "28" bytes4! float!;
-    f27 "27" bytes4! float!;
-    f26 "26" bytes4! float!;
-    f25 "25" bytes4! float!;
-    f24 "24" bytes4! float!;
-    f23 "23" bytes4! float!;
-    f22 "22" bytes4! float!;
-    f21 "21" bytes4! float!;
-    f20 "20" bytes4! float!;
-    f19 "19" bytes4! float!;
-    f18 "18" bytes4! float!;
-    f17 "17" bytes4! float!;
-    f16 "16" bytes4! float!;
-    f15 "15" bytes4! float!;
+    r12 "r12" bytes4! int! volatile; 
+    r11 "r11" bytes4! int! volatile; 
+    r10 "r10" bytes4! int! volatile; 
+    r9  "r9"  bytes4! int! volatile;
+    r8  "r8"  bytes4! int! volatile;
+    r7  "r7"  bytes4! int! volatile;
+    r6  "r6"  bytes4! int! volatile;
+    r5  "r5"  bytes4! int! volatile;
+    r4  "r4"  bytes4! int! volatile;
+    r3  "r3"  bytes4! int! ret volatile;
+
+    r31 "r31" bytes4! int!; 
+    r30 "r30" bytes4! int!; 
+    r29 "r29" bytes4! int!; 
+    r28 "r28" bytes4! int!; 
+    r27 "r27" bytes4! int!; 
+    r26 "r26" bytes4! int!; 
+    r25 "r25" bytes4! int!; 
+    r24 "r24" bytes4! int!; 
+    r23 "r23" bytes4! int!; 
+    r22 "r22" bytes4! int!; 
+    r21 "r21" bytes4! int!; 
+    r20 "r20" bytes4! int!; 
+    r19 "r19" bytes4! int!; 
+    r18 "r18" bytes4! int!; 
+    r17 "r17" bytes4! int!; 
+    r16 "r16" bytes4! int!;
+    r15 "r15" bytes4! int!;
+    r14 "r14" bytes4! int!;
+
+    f14 "f14" bytes4! float! volatile;
+    f13 "f13" bytes4! float! volatile;
+    f12 "f12" bytes4! float! volatile;
+    f11 "f11" bytes4! float! volatile;
+    f10 "f10" bytes4! float! volatile;
+    f9  "f9"  bytes4! float! volatile;
+    f8  "f8"  bytes4! float! volatile;
+    f7  "f7"  bytes4! float! volatile;
+    f6  "f6"  bytes4! float! volatile;
+    f5  "f5"  bytes4! float! volatile;
+    f4  "f4"  bytes4! float! volatile;
+    f3  "f3"  bytes4! float! volatile;
+    f2  "f2"  bytes4! float! volatile;
+    f1  "f1"  bytes4! float! volatile;
+    f0  "f0"  bytes4! float! volatile;
+
+    f31 "f31" bytes4! float!;
+    f30 "f30" bytes4! float!;
+    f29 "f29" bytes4! float!;
+    f28 "f28" bytes4! float!;
+    f27 "f27" bytes4! float!;
+    f26 "f26" bytes4! float!;
+    f25 "f25" bytes4! float!;
+    f24 "f24" bytes4! float!;
+    f23 "f23" bytes4! float!;
+    f22 "f22" bytes4! float!;
+    f21 "f21" bytes4! float!;
+    f20 "f20" bytes4! float!;
+    f19 "f19" bytes4! float!;
+    f18 "f18" bytes4! float!;
+    f17 "f17" bytes4! float!;
+    f16 "f16" bytes4! float!;
+    f15 "f15" bytes4! float!;
             
        cr0 "cr0" cr!;
 
@@ -109,10 +109,6 @@ PATTERNS
                emit "addi sp, sp, 4"
                cost 8;
                
-       RET
-               emit "ret"
-               cost 4;
-
        SETRET4(in:(ret)reg)
                emit "! setret4"
                cost 4;
@@ -402,6 +398,11 @@ PATTERNS
                emit "addi %out, %left, $right"
                cost 4;
 
+       out:(int)reg = ADD4(left:CONST4, right:(int)reg)
+        when signed_constant(%left, 16)
+               emit "addi %out, %right, $left"
+               cost 4;
+
        out:(int)reg = SUB4(left:(int)reg, right:(int)reg)
                emit "subf %out, %left, %right"
                cost 4;
index 7f0abd1..80433ec 100644 (file)
@@ -1,5 +1,6 @@
 #include "mcg.h"
 
+static struct procedure* current_proc;
 static struct basicblock* current_bb;
 
 static int stackptr;
@@ -712,9 +713,25 @@ static void insn_ivalue(int opcode, arith value)
                 );
             }
 
+            if (!current_proc->exit)
+            {
+                current_proc->exit = bb_get(NULL);
+                array_append(&current_proc->blocks, current_proc->exit);
+
+                /* This is actually ignored --- the entire block gets special
+                 * treatment. But a lot of the rest of the code assumes that
+                 * all basic blocks have one instruction, so we insert one. */
+                array_append(&current_proc->exit->irs,
+                    new_ir0(
+                        IR_RET, 0
+                    )
+                );
+            }
+
             appendir(
-                new_ir0(
-                    IR_RET, 0
+                new_ir1(
+                    IR_JUMP, 0,
+                    new_bbir(current_proc->exit)
                 )
             );
             break;
@@ -971,10 +988,11 @@ static void generate_tree(struct basicblock* bb)
     assert(stackptr == 0);
 }
 
-void tb_procedure(struct procedure* current_proc)
+void tb_procedure(struct procedure* proc)
 {
     int i;
 
+    current_proc = proc;
     for (i=0; i<current_proc->blocks.count; i++)
         generate_tree(current_proc->blocks.item[i]);
 
index aa57566..8606755 100644 (file)
@@ -70,13 +70,14 @@ definerule("mcgg",
                        cwd = e.cwd,
                        outleaves = {
                                "tables.c",
+                               "tables.h",
                        },
                        ins = {
                                "util/mcgg+mcgg",
                                e.srcs[1]
                        },
                        commands = {
-                               "%{ins[1]} -i %{ins[2]} -o %{outs}",
+                               "%{ins[1]} -i %{ins[2]} -o %{outs[1]} -h %{outs[2]}",
                        }
                }
        end
index 9155271..067ad3d 100644 (file)
@@ -180,8 +180,6 @@ predicate_arg
 #include <ctype.h>
 
 int errcnt = 0;
-FILE *infp = NULL;
-FILE *outfp = NULL;
 static char buf[BUFSIZ], *bp = buf;
 static int ppercent = 0;
 
index 3908532..39cdf97 100644 (file)
@@ -20,6 +20,10 @@ static char rcsid[] = "$Id$";
 
 int maxcost = SHRT_MAX / 2;
 
+FILE* infp = NULL;
+FILE* outfp = NULL;
+FILE* hdrfp = NULL;
+
 static char* prefix = "burm";
 static int Tflag = 1; /* tracing */
 static int ntnumber = 0;
@@ -32,8 +36,8 @@ static int nrules;
 static SMAPOF(struct reg) registers;
 static SMAPOF(struct regattr) registerattrs;
 
-static void print(char* fmt, ...);
-static void ckreach(Nonterm p);
+static void print(const char* fmt, ...);
+static void printh(const char* fmt, ...);
 static void registerterminals(void);
 static struct regattr* makeregattr(const char* id);
 static void emitclosure(Nonterm nts);
@@ -72,11 +76,12 @@ int main(int argc, char* argv[])
 
        infp = stdin;
        outfp = stdout;
+       hdrfp = NULL;
        yy_flex_debug = 0;
 
        for (;;)
        {
-               int opt = getopt(argc, argv, "p:i:o:yf");
+               int opt = getopt(argc, argv, "p:i:o:h:yf");
                if (opt == -1)
                        break;
 
@@ -104,6 +109,15 @@ int main(int argc, char* argv[])
                                }
                                break;
 
+                       case 'h':
+                               hdrfp = fopen(optarg, "w");
+                               if (!hdrfp)
+                               {
+                                       yyerror("cannot open output header file: %s\n", strerror(errno));
+                                       exit(1);
+                               }
+                               break;
+
                        case 'y':
                        {
                                extern int yydebug;
@@ -138,25 +152,19 @@ int main(int argc, char* argv[])
                const static struct terminfo reg = { "reg", NULL, "" };
                const static struct terminfo REG = { "REG", NULL, NULL };
                const static struct terminfo NOP = { "NOP", NULL, NULL };
+               const static struct terminfo RET = { "RET", NULL, NULL };
 
                nonterm("reg", true);
 
                rule(NULL, tree(&reg, NULL, NULL))->cost = 1;
                rule(&reg, tree(&REG, NULL, NULL))->cost = 1;
                rule(&reg, tree(&NOP, tree(&reg, NULL, NULL), NULL))->cost = 1;
+               rule(NULL, tree(&RET, NULL, NULL))->cost = 1;
        }
 
        yyin = infp;
        yyparse();
 
-       if (start)
-               ckreach(start);
-       #if 0
-       for (p = nts; p; p = p->link)
-               if (!p->reached)
-                       yyerror("can't reach non-terminal `%s'\n", p->name);
-       #endif
-
        emitregisterattrs();
        emitregisters();
        emitdefs(nts, ntnumber);
@@ -177,6 +185,13 @@ int main(int argc, char* argv[])
        emitfuncs();
        print("#endif\n");
        print("#include \"mcgg_generated_footer.h\"\n");
+       printh("#endif\n");
+
+       if (outfp)
+               fclose(outfp);
+       if (hdrfp)
+               fclose(hdrfp);
+
        return errcnt > 0;
 }
 
@@ -470,29 +485,30 @@ Rule rule(const struct terminfo* ti, Tree pattern)
 }
 
 /* print - formatted output */
-static void print(char* fmt, ...)
+
+static void printto(FILE* fp, const char* fmt, va_list ap)
 {
-       va_list ap;
+       if (!fp)
+               return;
 
-       va_start(ap, fmt);
        for (; *fmt; fmt++)
                if (*fmt == '%')
                        switch (*++fmt)
                        {
                                case 'd':
-                                       fprintf(outfp, "%d", va_arg(ap, int));
+                                       fprintf(fp, "%d", va_arg(ap, int));
                                        break;
 
                                case 'x':
-                                       fprintf(outfp, "%x", va_arg(ap, uint32_t));
+                                       fprintf(fp, "%x", va_arg(ap, uint32_t));
                                        break;
 
                                case 's':
-                                       fputs(va_arg(ap, char*), outfp);
+                                       fputs(va_arg(ap, char*), fp);
                                        break;
 
                                case 'P':
-                                       fprintf(outfp, "%s_", prefix);
+                                       fprintf(fp, "%s_", prefix);
                                        break;
 
                                case 'T':
@@ -514,7 +530,7 @@ static void print(char* fmt, ...)
                                }
 
                                case 'S':
-                                       fputs(va_arg(ap, Term)->name, outfp);
+                                       fputs(va_arg(ap, Term)->name, fp);
                                        break;
 
                                case '1':
@@ -525,46 +541,32 @@ static void print(char* fmt, ...)
                                {
                                        int n = *fmt - '0';
                                        while (n-- > 0)
-                                               putc('\t', outfp);
+                                               putc('\t', fp);
                                        break;
                                }
 
                                default:
-                                       putc(*fmt, outfp);
+                                       putc(*fmt, fp);
                                        break;
                        }
                else
-                       putc(*fmt, outfp);
-       va_end(ap);
+                       putc(*fmt, fp);
 }
 
-void printlineno(void)
+static void print(const char* fmt, ...)
 {
-       //print("#line %d\n", yylineno);
-}
-
-/* reach - mark all non-terminals in tree t as reachable */
-static void reach(Tree t)
-{
-       Nonterm p = t->op;
-
-       if (p->kind == NONTERM)
-               if (!p->reached)
-                       ckreach(p);
-       if (t->left)
-               reach(t->left);
-       if (t->right)
-               reach(t->right);
+       va_list ap;
+       va_start(ap, fmt);
+       printto(outfp, fmt, ap);
+       va_end(ap);
 }
 
-/* ckreach - mark all non-terminals reachable from p */
-static void ckreach(Nonterm p)
+static void printh(const char* fmt, ...)
 {
-       Rule r;
-
-       p->reached = 1;
-       for (r = p->rules; r; r = r->decode)
-               reach(r->pattern);
+       va_list ap;
+       va_start(ap, fmt);
+       printto(hdrfp, fmt, ap);
+       va_end(ap);
 }
 
 static void emitregisterattrs(void)
@@ -578,8 +580,10 @@ static void emitregisterattrs(void)
                assert(rc->number == i);
 
                print("%1\"%s\",\n", rc->name);
+               printh("#define %P%s_ATTR (1U<<%d)\n", rc->name, rc->number);
        }
        print("};\n\n");
+       printh("\n");
 }
 
 static void emitregisters(void)
@@ -713,9 +717,12 @@ static void emitdefs(Nonterm nts, int ntnumber)
 {
        Nonterm p;
 
+       printh("enum {\n");
        for (p = nts; p; p = p->link)
-               print("#define %P%S_NT %d\n", p, p->number);
-       print("#define %Pmax_nt %d\n\n", ntnumber);
+               printh("%1%P%S_NT = %d,\n", p, p->number);
+       printh("%1%Pmax_nt = %d\n", ntnumber);
+       printh("};\n\n");
+
        print("const char *%Pntname[] = {\n%10,\n");
        for (p = nts; p; p = p->link)
                print("%1\"%S\",\n", p);
@@ -744,6 +751,9 @@ static void emitheader(void)
        print("#include \"mcgg_generated_header.h\"\n");
        if (Tflag)
                print("static NODEPTR_TYPE %Pnp;\n\n");
+
+       printh("#ifndef MCG_DEFS_H\n");
+       printh("#define MCG_DEFS_H\n\n");
 }
 
 /* computekids - compute paths to kids in tree t */
@@ -1343,11 +1353,6 @@ static void emitterms(Term terms)
        Term p;
        int k;
 
-       print("enum {\n");
-       for (k = 0, p = terms; p; p = p->link)
-               print("%1%S = %d,\n", p, p->esn);
-       print("};\n\n");
-
        print("static const char %Parity[] = {\n");
        for (k = 0, p = terms; p; p = p->link)
        {
index 48397c2..d12985e 100644 (file)
@@ -143,6 +143,7 @@ void yywarn(char* fmt, ...);
 extern int errcnt;
 extern FILE* infp;
 extern FILE* outfp;
+extern FILE* hdrfp;
 
 /* Stupid flex imports --- why mo header file? */