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",
"modules/src/read_em+lib_ev",
"modules/src/string+lib",
"modules/src/system+lib",
- "./*.h",
+ "util/mcgg+lib",
},
vars = {
["+cflags"] = {
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;
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);
#include "basicblock.h"
#include "procedure.h"
#include "graph.h"
+#include "tables.h"
extern char em_pseu[][4];
extern char em_mnem[][4];
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;
#include "mcg.h"
#include "mcgg.h"
-
#define PANIC printf
#define burm_assert(b, s) assert(b)
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);
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;
}
}
if (!insnno)
burm_panic_cannot_match(shadow);
- walk_instructions(shadow, 1);
+ walk_instructions(shadow, burm_stmt_NT);
}
}
}
--- /dev/null
+#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 : */
+
+
}
}
-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);
{
/* Copy. */
- hop = create_move(bb, src, dest);
+ hop = platform_move(bb, src, dest);
pmap_remove(&copies, src, dest);
}
else
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);
}
--- /dev/null
+#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 : */
+
pass_live_vreg_analysis();
print_hops('8', proc);
pass_register_allocator();
+ pass_add_prologue_epilogue(proc);
print_hops('9', proc);
emit_procedure(proc);
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;
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;
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
* 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!;
emit "addi sp, sp, 4"
cost 8;
- RET
- emit "ret"
- cost 4;
-
SETRET4(in:(ret)reg)
emit "! setret4"
cost 4;
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;
#include "mcg.h"
+static struct procedure* current_proc;
static struct basicblock* current_bb;
static int stackptr;
);
}
+ 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;
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]);
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
#include <ctype.h>
int errcnt = 0;
-FILE *infp = NULL;
-FILE *outfp = NULL;
static char buf[BUFSIZ], *bp = buf;
static int ppercent = 0;
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;
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);
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;
}
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;
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);
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;
}
}
/* 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':
}
case 'S':
- fputs(va_arg(ap, Term)->name, outfp);
+ fputs(va_arg(ap, Term)->name, fp);
break;
case '1':
{
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)
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)
{
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);
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 */
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)
{
extern int errcnt;
extern FILE* infp;
extern FILE* outfp;
+extern FILE* hdrfp;
/* Stupid flex imports --- why mo header file? */