From 9504aec2bdae275343f5d95497abfd61f70da3c7 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 15 Oct 2016 18:38:46 +0200 Subject: [PATCH] Function termination gets routed through an exit block; we now have prologues and epilogues. mcgg now exports some useful data as headers. Start factoring out some of the architecture-specific bits into an architecture-specific file. --- mach/proto/mcg/build.lua | 7 +- mach/proto/mcg/hop.c | 49 ++++++++ mach/proto/mcg/hop.h | 2 + mach/proto/mcg/mcg.h | 6 + mach/proto/mcg/mcgg_generated_header.h | 1 - mach/proto/mcg/parse_em.c | 4 +- mach/proto/mcg/pass_instructionselection.c | 4 +- mach/proto/mcg/pass_prologueepilogue.c | 19 +++ mach/proto/mcg/pass_registerallocator.c | 17 +-- mach/proto/mcg/powerpc.c | 41 +++++++ mach/proto/mcg/procedure.c | 1 + mach/proto/mcg/procedure.h | 3 +- mach/proto/mcg/reg.c | 6 +- mach/proto/mcg/reg.h | 2 +- mach/proto/mcg/table | 129 +++++++++++---------- mach/proto/mcg/treebuilder.c | 24 +++- util/mcgg/build.lua | 3 +- util/mcgg/gram.y | 2 - util/mcgg/iburg.c | 117 ++++++++++--------- util/mcgg/iburg.h | 1 + 20 files changed, 285 insertions(+), 153 deletions(-) create mode 100644 mach/proto/mcg/pass_prologueepilogue.c create mode 100644 mach/proto/mcg/powerpc.c diff --git a/mach/proto/mcg/build.lua b/mach/proto/mcg/build.lua index 0626c4a3c..8fc41be95 100644 --- a/mach/proto/mcg/build.lua +++ b/mach/proto/mcg/build.lua @@ -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"] = { diff --git a/mach/proto/mcg/hop.c b/mach/proto/mcg/hop.c index a362f8b79..3797d7b24 100644 --- a/mach/proto/mcg/hop.c +++ b/mach/proto/mcg/hop.c @@ -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; diff --git a/mach/proto/mcg/hop.h b/mach/proto/mcg/hop.h index 1dbf5772c..dcc6fe03b 100644 --- a/mach/proto/mcg/hop.h +++ b/mach/proto/mcg/hop.h @@ -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); diff --git a/mach/proto/mcg/mcg.h b/mach/proto/mcg/mcg.h index 0df947df7..5cd875ef4 100644 --- a/mach/proto/mcg/mcg.h +++ b/mach/proto/mcg/mcg.h @@ -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; diff --git a/mach/proto/mcg/mcgg_generated_header.h b/mach/proto/mcg/mcgg_generated_header.h index 5d9b3ae2e..f0bfa99a0 100644 --- a/mach/proto/mcg/mcgg_generated_header.h +++ b/mach/proto/mcg/mcgg_generated_header.h @@ -1,7 +1,6 @@ #include "mcg.h" #include "mcgg.h" - #define PANIC printf #define burm_assert(b, s) assert(b) diff --git a/mach/proto/mcg/parse_em.c b/mach/proto/mcg/parse_em.c index 27e3a8dda..2b88eac81 100644 --- a/mach/proto/mcg/parse_em.c +++ b/mach/proto/mcg/parse_em.c @@ -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(¤t_proc->blocks, code_bb); diff --git a/mach/proto/mcg/pass_instructionselection.c b/mach/proto/mcg/pass_instructionselection.c index 9b5a615c6..752648de5 100644 --- a/mach/proto/mcg/pass_instructionselection.c +++ b/mach/proto/mcg/pass_instructionselection.c @@ -205,7 +205,7 @@ static struct insn* walk_instructions(struct burm_node* node, int goal) hop_print('I', current_hop); array_append(¤t_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 index 000000000..056630707 --- /dev/null +++ b/mach/proto/mcg/pass_prologueepilogue.c @@ -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 : */ + + diff --git a/mach/proto/mcg/pass_registerallocator.c b/mach/proto/mcg/pass_registerallocator.c index fffc6a138..f967e3136 100644 --- a/mach/proto/mcg/pass_registerallocator.c +++ b/mach/proto/mcg/pass_registerallocator.c @@ -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 index 000000000..b5c606110 --- /dev/null +++ b/mach/proto/mcg/powerpc.c @@ -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 : */ + diff --git a/mach/proto/mcg/procedure.c b/mach/proto/mcg/procedure.c index af05f80e3..d6382b06d 100644 --- a/mach/proto/mcg/procedure.c +++ b/mach/proto/mcg/procedure.c @@ -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); diff --git a/mach/proto/mcg/procedure.h b/mach/proto/mcg/procedure.h index 2414db050..9d653b3f4 100644 --- a/mach/proto/mcg/procedure.h +++ b/mach/proto/mcg/procedure.h @@ -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; diff --git a/mach/proto/mcg/reg.c b/mach/proto/mcg/reg.c index bb7266504..2cb523764 100644 --- a/mach/proto/mcg/reg.c +++ b/mach/proto/mcg/reg.c @@ -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; diff --git a/mach/proto/mcg/reg.h b/mach/proto/mcg/reg.h index f1b5e1b05..0f47dfd03 100644 --- a/mach/proto/mcg/reg.h +++ b/mach/proto/mcg/reg.h @@ -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 diff --git a/mach/proto/mcg/table b/mach/proto/mcg/table index 6a24d9e6b..24b9d6e32 100644 --- a/mach/proto/mcg/table +++ b/mach/proto/mcg/table @@ -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; + 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 "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!; + 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 "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; + 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 "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!; + 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; diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 7f0abd19d..80433ec7d 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -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(¤t_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(¤t_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; iblocks.count; i++) generate_tree(current_proc->blocks.item[i]); diff --git a/util/mcgg/build.lua b/util/mcgg/build.lua index aa575667a..8606755c7 100644 --- a/util/mcgg/build.lua +++ b/util/mcgg/build.lua @@ -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 diff --git a/util/mcgg/gram.y b/util/mcgg/gram.y index 9155271fc..067ad3d8d 100644 --- a/util/mcgg/gram.y +++ b/util/mcgg/gram.y @@ -180,8 +180,6 @@ predicate_arg #include int errcnt = 0; -FILE *infp = NULL; -FILE *outfp = NULL; static char buf[BUFSIZ], *bp = buf; static int ppercent = 0; diff --git a/util/mcgg/iburg.c b/util/mcgg/iburg.c index 390853201..39cdf9729 100644 --- a/util/mcgg/iburg.c +++ b/util/mcgg/iburg.c @@ -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(®, NULL, NULL))->cost = 1; rule(®, tree(®, NULL, NULL))->cost = 1; rule(®, tree(&NOP, tree(®, 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, ...) -{ - va_list ap; - va_start(ap, fmt); +static void printto(FILE* fp, const char* fmt, va_list ap) +{ + if (!fp) + return; + 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); + putc(*fmt, fp); +} + +static void print(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + printto(outfp, fmt, ap); va_end(ap); } -void printlineno(void) +static void printh(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); -} - -/* ckreach - mark all non-terminals reachable from p */ -static void ckreach(Nonterm p) -{ - 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) { diff --git a/util/mcgg/iburg.h b/util/mcgg/iburg.h index 48397c21e..d12985eb6 100644 --- a/util/mcgg/iburg.h +++ b/util/mcgg/iburg.h @@ -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? */