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.
This commit is contained in:
parent
5ad3aa8595
commit
9504aec2bd
|
@ -9,10 +9,11 @@ cprogram {
|
||||||
name = "mcg",
|
name = "mcg",
|
||||||
srcs = {
|
srcs = {
|
||||||
"./*.c",
|
"./*.c",
|
||||||
"+mcgg_c",
|
matching(filenamesof("+mcgg_c"), "%.c$"),
|
||||||
},
|
},
|
||||||
deps = {
|
deps = {
|
||||||
"util/mcgg+lib",
|
"+mcgg_c",
|
||||||
|
"./*.h",
|
||||||
"h+emheaders",
|
"h+emheaders",
|
||||||
"modules+headers",
|
"modules+headers",
|
||||||
"modules/src/alloc+lib",
|
"modules/src/alloc+lib",
|
||||||
|
@ -23,7 +24,7 @@ cprogram {
|
||||||
"modules/src/read_em+lib_ev",
|
"modules/src/read_em+lib_ev",
|
||||||
"modules/src/string+lib",
|
"modules/src/string+lib",
|
||||||
"modules/src/system+lib",
|
"modules/src/system+lib",
|
||||||
"./*.h",
|
"util/mcgg+lib",
|
||||||
},
|
},
|
||||||
vars = {
|
vars = {
|
||||||
["+cflags"] = {
|
["+cflags"] = {
|
||||||
|
|
|
@ -58,6 +58,55 @@ void hop_add_eoi_insel(struct hop* hop)
|
||||||
array_append(&hop->insels, insel);
|
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)
|
static void print_header(char k, struct hop* hop)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -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_value_insel(struct hop* hop, struct ir* ir);
|
||||||
extern void hop_add_eoi_insel(struct hop* hop);
|
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 char* hop_render(struct hop* hop);
|
||||||
extern void hop_print(char k, struct hop* hop);
|
extern void hop_print(char k, struct hop* hop);
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "basicblock.h"
|
#include "basicblock.h"
|
||||||
#include "procedure.h"
|
#include "procedure.h"
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
#include "tables.h"
|
||||||
|
|
||||||
extern char em_pseu[][4];
|
extern char em_pseu[][4];
|
||||||
extern char em_mnem[][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_insert_moves(void);
|
||||||
extern void pass_instruction_selector(void);
|
extern void pass_instruction_selector(void);
|
||||||
extern void pass_live_vreg_analysis(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_promote_float_ops(struct procedure* proc);
|
||||||
extern void pass_register_allocator(void);
|
extern void pass_register_allocator(void);
|
||||||
extern void pass_remove_dead_blocks(struct procedure* proc);
|
extern void pass_remove_dead_blocks(struct procedure* proc);
|
||||||
extern void pass_remove_dead_phis(void);
|
extern void pass_remove_dead_phis(void);
|
||||||
extern void pass_split_critical_edges(struct procedure* proc);
|
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* outputfile;
|
||||||
extern FILE* dominance_dot_file;
|
extern FILE* dominance_dot_file;
|
||||||
extern FILE* cfg_dot_file;
|
extern FILE* cfg_dot_file;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "mcg.h"
|
#include "mcg.h"
|
||||||
#include "mcgg.h"
|
#include "mcgg.h"
|
||||||
|
|
||||||
|
|
||||||
#define PANIC printf
|
#define PANIC printf
|
||||||
|
|
||||||
#define burm_assert(b, s) assert(b)
|
#define burm_assert(b, s) assert(b)
|
||||||
|
|
|
@ -307,9 +307,9 @@ static void parse_pseu(void)
|
||||||
|
|
||||||
current_proc = calloc(sizeof(struct procedure), 1);
|
current_proc = calloc(sizeof(struct procedure), 1);
|
||||||
current_proc->name = strdup(em.em_pnam);
|
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;
|
current_proc->nlocals = em.em_nlocals;
|
||||||
code_bb = current_proc->root_bb;
|
code_bb = current_proc->entry;
|
||||||
code_bb->is_root = true;
|
code_bb->is_root = true;
|
||||||
array_append(¤t_proc->blocks, code_bb);
|
array_append(¤t_proc->blocks, code_bb);
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,7 @@ static struct insn* walk_instructions(struct burm_node* node, int goal)
|
||||||
hop_print('I', current_hop);
|
hop_print('I', current_hop);
|
||||||
array_append(¤t_bb->hops, current_hop);
|
array_append(¤t_bb->hops, current_hop);
|
||||||
|
|
||||||
if (goal != 1)
|
if (goal != burm_stmt_NT)
|
||||||
insn->ir->result = insn->hop->output;
|
insn->ir->result = insn->hop->output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ static void select_instructions(void)
|
||||||
if (!insnno)
|
if (!insnno)
|
||||||
burm_panic_cannot_match(shadow);
|
burm_panic_cannot_match(shadow);
|
||||||
|
|
||||||
walk_instructions(shadow, 1);
|
walk_instructions(shadow, burm_stmt_NT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
19
mach/proto/mcg/pass_prologueepilogue.c
Normal file
19
mach/proto/mcg/pass_prologueepilogue.c
Normal file
|
@ -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 : */
|
||||||
|
|
||||||
|
|
|
@ -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)
|
static struct hop* create_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest)
|
||||||
{
|
{
|
||||||
struct hop* hop = new_hop(bb, NULL);
|
struct hop* hop = new_hop(bb, NULL);
|
||||||
|
@ -558,7 +545,7 @@ static int insert_moves(struct basicblock* bb, int index,
|
||||||
{
|
{
|
||||||
/* Copy. */
|
/* Copy. */
|
||||||
|
|
||||||
hop = create_move(bb, src, dest);
|
hop = platform_move(bb, src, dest);
|
||||||
pmap_remove(&copies, src, dest);
|
pmap_remove(&copies, src, dest);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -567,7 +554,7 @@ static int insert_moves(struct basicblock* bb, int index,
|
||||||
|
|
||||||
src = copies.item[0].left;
|
src = copies.item[0].left;
|
||||||
dest = pmap_findleft(&copies, src);
|
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, src, dest);
|
||||||
pmap_remove(&copies, dest, src);
|
pmap_remove(&copies, dest, src);
|
||||||
}
|
}
|
||||||
|
|
41
mach/proto/mcg/powerpc.c
Normal file
41
mach/proto/mcg/powerpc.c
Normal file
|
@ -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 : */
|
||||||
|
|
|
@ -190,6 +190,7 @@ void procedure_compile(struct procedure* proc)
|
||||||
pass_live_vreg_analysis();
|
pass_live_vreg_analysis();
|
||||||
print_hops('8', proc);
|
print_hops('8', proc);
|
||||||
pass_register_allocator();
|
pass_register_allocator();
|
||||||
|
pass_add_prologue_epilogue(proc);
|
||||||
print_hops('9', proc);
|
print_hops('9', proc);
|
||||||
|
|
||||||
emit_procedure(proc);
|
emit_procedure(proc);
|
||||||
|
|
|
@ -11,7 +11,8 @@ struct local
|
||||||
struct procedure
|
struct procedure
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
struct basicblock* root_bb;
|
struct basicblock* entry;
|
||||||
|
struct basicblock* exit;
|
||||||
size_t nlocals;
|
size_t nlocals;
|
||||||
ARRAYOF(struct basicblock) blocks;
|
ARRAYOF(struct basicblock) blocks;
|
||||||
IMAPOF(struct local) locals;
|
IMAPOF(struct local) locals;
|
||||||
|
|
|
@ -14,17 +14,19 @@ struct hreg* new_hreg(const struct burm_register_data* brd)
|
||||||
struct hreg* hreg = calloc(1, sizeof *hreg);
|
struct hreg* hreg = calloc(1, sizeof *hreg);
|
||||||
hreg->name = brd->name;
|
hreg->name = brd->name;
|
||||||
hreg->realname = brd->realname;
|
hreg->realname = brd->realname;
|
||||||
|
hreg->type = brd->type;
|
||||||
hreg->attrs = brd->attrs;
|
hreg->attrs = brd->attrs;
|
||||||
hreg->is_stacked = false;
|
hreg->is_stacked = false;
|
||||||
return hreg;
|
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);
|
struct hreg* hreg = calloc(1, sizeof *hreg);
|
||||||
hreg->name = aprintf("stacked_%d", offset);
|
hreg->name = aprintf("stacked_%d", offset);
|
||||||
hreg->realname = hreg->name;
|
hreg->realname = hreg->name;
|
||||||
hreg->attrs = attrs;
|
hreg->type = type;
|
||||||
|
hreg->attrs = type;
|
||||||
hreg->is_stacked = true;
|
hreg->is_stacked = true;
|
||||||
hreg->offset = offset;
|
hreg->offset = offset;
|
||||||
return hreg;
|
return hreg;
|
||||||
|
|
|
@ -34,7 +34,7 @@ typedef PMAPOF(struct hreg, struct vreg) register_assignment_t;
|
||||||
extern struct vreg* new_vreg(void);
|
extern struct vreg* new_vreg(void);
|
||||||
|
|
||||||
extern struct hreg* new_hreg(const struct burm_register_data* brd);
|
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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -7,69 +7,69 @@ REGISTERS
|
||||||
* a register into another register (e.g. for eviction).
|
* a register into another register (e.g. for eviction).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
r12 "12" bytes4! int! volatile;
|
r12 "r12" bytes4! int! volatile;
|
||||||
r11 "11" bytes4! int! volatile;
|
r11 "r11" bytes4! int! volatile;
|
||||||
r10 "10" bytes4! int! volatile;
|
r10 "r10" bytes4! int! volatile;
|
||||||
r9 "9" bytes4! int! volatile;
|
r9 "r9" bytes4! int! volatile;
|
||||||
r8 "8" bytes4! int! volatile;
|
r8 "r8" bytes4! int! volatile;
|
||||||
r7 "7" bytes4! int! volatile;
|
r7 "r7" bytes4! int! volatile;
|
||||||
r6 "6" bytes4! int! volatile;
|
r6 "r6" bytes4! int! volatile;
|
||||||
r5 "5" bytes4! int! volatile;
|
r5 "r5" bytes4! int! volatile;
|
||||||
r4 "4" bytes4! int! volatile;
|
r4 "r4" bytes4! int! volatile;
|
||||||
r3 "3" bytes4! int! ret volatile;
|
r3 "r3" bytes4! int! ret volatile;
|
||||||
|
|
||||||
r31 "31" bytes4! int!;
|
r31 "r31" bytes4! int!;
|
||||||
r30 "30" bytes4! int!;
|
r30 "r30" bytes4! int!;
|
||||||
r29 "29" bytes4! int!;
|
r29 "r29" bytes4! int!;
|
||||||
r28 "28" bytes4! int!;
|
r28 "r28" bytes4! int!;
|
||||||
r27 "27" bytes4! int!;
|
r27 "r27" bytes4! int!;
|
||||||
r26 "26" bytes4! int!;
|
r26 "r26" bytes4! int!;
|
||||||
r25 "25" bytes4! int!;
|
r25 "r25" bytes4! int!;
|
||||||
r24 "24" bytes4! int!;
|
r24 "r24" bytes4! int!;
|
||||||
r23 "23" bytes4! int!;
|
r23 "r23" bytes4! int!;
|
||||||
r22 "22" bytes4! int!;
|
r22 "r22" bytes4! int!;
|
||||||
r21 "21" bytes4! int!;
|
r21 "r21" bytes4! int!;
|
||||||
r20 "20" bytes4! int!;
|
r20 "r20" bytes4! int!;
|
||||||
r19 "19" bytes4! int!;
|
r19 "r19" bytes4! int!;
|
||||||
r18 "18" bytes4! int!;
|
r18 "r18" bytes4! int!;
|
||||||
r17 "17" bytes4! int!;
|
r17 "r17" bytes4! int!;
|
||||||
r16 "16" bytes4! int!;
|
r16 "r16" bytes4! int!;
|
||||||
r15 "15" bytes4! int!;
|
r15 "r15" bytes4! int!;
|
||||||
r14 "14" bytes4! int!;
|
r14 "r14" bytes4! int!;
|
||||||
|
|
||||||
f14 "14" bytes4! float! volatile;
|
f14 "f14" bytes4! float! volatile;
|
||||||
f13 "13" bytes4! float! volatile;
|
f13 "f13" bytes4! float! volatile;
|
||||||
f12 "12" bytes4! float! volatile;
|
f12 "f12" bytes4! float! volatile;
|
||||||
f11 "11" bytes4! float! volatile;
|
f11 "f11" bytes4! float! volatile;
|
||||||
f10 "10" bytes4! float! volatile;
|
f10 "f10" bytes4! float! volatile;
|
||||||
f9 "9" bytes4! float! volatile;
|
f9 "f9" bytes4! float! volatile;
|
||||||
f8 "8" bytes4! float! volatile;
|
f8 "f8" bytes4! float! volatile;
|
||||||
f7 "7" bytes4! float! volatile;
|
f7 "f7" bytes4! float! volatile;
|
||||||
f6 "6" bytes4! float! volatile;
|
f6 "f6" bytes4! float! volatile;
|
||||||
f5 "5" bytes4! float! volatile;
|
f5 "f5" bytes4! float! volatile;
|
||||||
f4 "4" bytes4! float! volatile;
|
f4 "f4" bytes4! float! volatile;
|
||||||
f3 "3" bytes4! float! volatile;
|
f3 "f3" bytes4! float! volatile;
|
||||||
f2 "2" bytes4! float! volatile;
|
f2 "f2" bytes4! float! volatile;
|
||||||
f1 "1" bytes4! float! volatile;
|
f1 "f1" bytes4! float! volatile;
|
||||||
f0 "0" bytes4! float! volatile;
|
f0 "f0" bytes4! float! volatile;
|
||||||
|
|
||||||
f31 "31" bytes4! float!;
|
f31 "f31" bytes4! float!;
|
||||||
f30 "30" bytes4! float!;
|
f30 "f30" bytes4! float!;
|
||||||
f29 "29" bytes4! float!;
|
f29 "f29" bytes4! float!;
|
||||||
f28 "28" bytes4! float!;
|
f28 "f28" bytes4! float!;
|
||||||
f27 "27" bytes4! float!;
|
f27 "f27" bytes4! float!;
|
||||||
f26 "26" bytes4! float!;
|
f26 "f26" bytes4! float!;
|
||||||
f25 "25" bytes4! float!;
|
f25 "f25" bytes4! float!;
|
||||||
f24 "24" bytes4! float!;
|
f24 "f24" bytes4! float!;
|
||||||
f23 "23" bytes4! float!;
|
f23 "f23" bytes4! float!;
|
||||||
f22 "22" bytes4! float!;
|
f22 "f22" bytes4! float!;
|
||||||
f21 "21" bytes4! float!;
|
f21 "f21" bytes4! float!;
|
||||||
f20 "20" bytes4! float!;
|
f20 "f20" bytes4! float!;
|
||||||
f19 "19" bytes4! float!;
|
f19 "f19" bytes4! float!;
|
||||||
f18 "18" bytes4! float!;
|
f18 "f18" bytes4! float!;
|
||||||
f17 "17" bytes4! float!;
|
f17 "f17" bytes4! float!;
|
||||||
f16 "16" bytes4! float!;
|
f16 "f16" bytes4! float!;
|
||||||
f15 "15" bytes4! float!;
|
f15 "f15" bytes4! float!;
|
||||||
|
|
||||||
cr0 "cr0" cr!;
|
cr0 "cr0" cr!;
|
||||||
|
|
||||||
|
@ -109,10 +109,6 @@ PATTERNS
|
||||||
emit "addi sp, sp, 4"
|
emit "addi sp, sp, 4"
|
||||||
cost 8;
|
cost 8;
|
||||||
|
|
||||||
RET
|
|
||||||
emit "ret"
|
|
||||||
cost 4;
|
|
||||||
|
|
||||||
SETRET4(in:(ret)reg)
|
SETRET4(in:(ret)reg)
|
||||||
emit "! setret4"
|
emit "! setret4"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
@ -402,6 +398,11 @@ PATTERNS
|
||||||
emit "addi %out, %left, $right"
|
emit "addi %out, %left, $right"
|
||||||
cost 4;
|
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)
|
out:(int)reg = SUB4(left:(int)reg, right:(int)reg)
|
||||||
emit "subf %out, %left, %right"
|
emit "subf %out, %left, %right"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "mcg.h"
|
#include "mcg.h"
|
||||||
|
|
||||||
|
static struct procedure* current_proc;
|
||||||
static struct basicblock* current_bb;
|
static struct basicblock* current_bb;
|
||||||
|
|
||||||
static int stackptr;
|
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(
|
appendir(
|
||||||
new_ir0(
|
new_ir1(
|
||||||
IR_RET, 0
|
IR_JUMP, 0,
|
||||||
|
new_bbir(current_proc->exit)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
@ -971,10 +988,11 @@ static void generate_tree(struct basicblock* bb)
|
||||||
assert(stackptr == 0);
|
assert(stackptr == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tb_procedure(struct procedure* current_proc)
|
void tb_procedure(struct procedure* proc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
current_proc = proc;
|
||||||
for (i=0; i<current_proc->blocks.count; i++)
|
for (i=0; i<current_proc->blocks.count; i++)
|
||||||
generate_tree(current_proc->blocks.item[i]);
|
generate_tree(current_proc->blocks.item[i]);
|
||||||
|
|
||||||
|
|
|
@ -70,13 +70,14 @@ definerule("mcgg",
|
||||||
cwd = e.cwd,
|
cwd = e.cwd,
|
||||||
outleaves = {
|
outleaves = {
|
||||||
"tables.c",
|
"tables.c",
|
||||||
|
"tables.h",
|
||||||
},
|
},
|
||||||
ins = {
|
ins = {
|
||||||
"util/mcgg+mcgg",
|
"util/mcgg+mcgg",
|
||||||
e.srcs[1]
|
e.srcs[1]
|
||||||
},
|
},
|
||||||
commands = {
|
commands = {
|
||||||
"%{ins[1]} -i %{ins[2]} -o %{outs}",
|
"%{ins[1]} -i %{ins[2]} -o %{outs[1]} -h %{outs[2]}",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -180,8 +180,6 @@ predicate_arg
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
int errcnt = 0;
|
int errcnt = 0;
|
||||||
FILE *infp = NULL;
|
|
||||||
FILE *outfp = NULL;
|
|
||||||
static char buf[BUFSIZ], *bp = buf;
|
static char buf[BUFSIZ], *bp = buf;
|
||||||
static int ppercent = 0;
|
static int ppercent = 0;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,10 @@ static char rcsid[] = "$Id$";
|
||||||
|
|
||||||
int maxcost = SHRT_MAX / 2;
|
int maxcost = SHRT_MAX / 2;
|
||||||
|
|
||||||
|
FILE* infp = NULL;
|
||||||
|
FILE* outfp = NULL;
|
||||||
|
FILE* hdrfp = NULL;
|
||||||
|
|
||||||
static char* prefix = "burm";
|
static char* prefix = "burm";
|
||||||
static int Tflag = 1; /* tracing */
|
static int Tflag = 1; /* tracing */
|
||||||
static int ntnumber = 0;
|
static int ntnumber = 0;
|
||||||
|
@ -32,8 +36,8 @@ static int nrules;
|
||||||
static SMAPOF(struct reg) registers;
|
static SMAPOF(struct reg) registers;
|
||||||
static SMAPOF(struct regattr) registerattrs;
|
static SMAPOF(struct regattr) registerattrs;
|
||||||
|
|
||||||
static void print(char* fmt, ...);
|
static void print(const char* fmt, ...);
|
||||||
static void ckreach(Nonterm p);
|
static void printh(const char* fmt, ...);
|
||||||
static void registerterminals(void);
|
static void registerterminals(void);
|
||||||
static struct regattr* makeregattr(const char* id);
|
static struct regattr* makeregattr(const char* id);
|
||||||
static void emitclosure(Nonterm nts);
|
static void emitclosure(Nonterm nts);
|
||||||
|
@ -72,11 +76,12 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
infp = stdin;
|
infp = stdin;
|
||||||
outfp = stdout;
|
outfp = stdout;
|
||||||
|
hdrfp = NULL;
|
||||||
yy_flex_debug = 0;
|
yy_flex_debug = 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int opt = getopt(argc, argv, "p:i:o:yf");
|
int opt = getopt(argc, argv, "p:i:o:h:yf");
|
||||||
if (opt == -1)
|
if (opt == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -104,6 +109,15 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
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':
|
case 'y':
|
||||||
{
|
{
|
||||||
extern int yydebug;
|
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, "" };
|
||||||
const static struct terminfo REG = { "REG", NULL, NULL };
|
const static struct terminfo REG = { "REG", NULL, NULL };
|
||||||
const static struct terminfo NOP = { "NOP", NULL, NULL };
|
const static struct terminfo NOP = { "NOP", NULL, NULL };
|
||||||
|
const static struct terminfo RET = { "RET", NULL, NULL };
|
||||||
|
|
||||||
nonterm("reg", true);
|
nonterm("reg", true);
|
||||||
|
|
||||||
rule(NULL, tree(®, NULL, NULL))->cost = 1;
|
rule(NULL, tree(®, NULL, NULL))->cost = 1;
|
||||||
rule(®, tree(®, NULL, NULL))->cost = 1;
|
rule(®, tree(®, NULL, NULL))->cost = 1;
|
||||||
rule(®, tree(&NOP, tree(®, NULL, NULL), NULL))->cost = 1;
|
rule(®, tree(&NOP, tree(®, NULL, NULL), NULL))->cost = 1;
|
||||||
|
rule(NULL, tree(&RET, NULL, NULL))->cost = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
yyin = infp;
|
yyin = infp;
|
||||||
yyparse();
|
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();
|
emitregisterattrs();
|
||||||
emitregisters();
|
emitregisters();
|
||||||
emitdefs(nts, ntnumber);
|
emitdefs(nts, ntnumber);
|
||||||
|
@ -177,6 +185,13 @@ int main(int argc, char* argv[])
|
||||||
emitfuncs();
|
emitfuncs();
|
||||||
print("#endif\n");
|
print("#endif\n");
|
||||||
print("#include \"mcgg_generated_footer.h\"\n");
|
print("#include \"mcgg_generated_footer.h\"\n");
|
||||||
|
printh("#endif\n");
|
||||||
|
|
||||||
|
if (outfp)
|
||||||
|
fclose(outfp);
|
||||||
|
if (hdrfp)
|
||||||
|
fclose(hdrfp);
|
||||||
|
|
||||||
return errcnt > 0;
|
return errcnt > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,29 +485,30 @@ Rule rule(const struct terminfo* ti, Tree pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* print - formatted output */
|
/* 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++)
|
for (; *fmt; fmt++)
|
||||||
if (*fmt == '%')
|
if (*fmt == '%')
|
||||||
switch (*++fmt)
|
switch (*++fmt)
|
||||||
{
|
{
|
||||||
case 'd':
|
case 'd':
|
||||||
fprintf(outfp, "%d", va_arg(ap, int));
|
fprintf(fp, "%d", va_arg(ap, int));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
fprintf(outfp, "%x", va_arg(ap, uint32_t));
|
fprintf(fp, "%x", va_arg(ap, uint32_t));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
fputs(va_arg(ap, char*), outfp);
|
fputs(va_arg(ap, char*), fp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
fprintf(outfp, "%s_", prefix);
|
fprintf(fp, "%s_", prefix);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'T':
|
case 'T':
|
||||||
|
@ -514,7 +530,7 @@ static void print(char* fmt, ...)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
fputs(va_arg(ap, Term)->name, outfp);
|
fputs(va_arg(ap, Term)->name, fp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '1':
|
case '1':
|
||||||
|
@ -525,46 +541,32 @@ static void print(char* fmt, ...)
|
||||||
{
|
{
|
||||||
int n = *fmt - '0';
|
int n = *fmt - '0';
|
||||||
while (n-- > 0)
|
while (n-- > 0)
|
||||||
putc('\t', outfp);
|
putc('\t', fp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
putc(*fmt, outfp);
|
putc(*fmt, fp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
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);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printlineno(void)
|
static void printh(const char* fmt, ...)
|
||||||
{
|
{
|
||||||
//print("#line %d\n", yylineno);
|
va_list ap;
|
||||||
}
|
va_start(ap, fmt);
|
||||||
|
printto(hdrfp, fmt, ap);
|
||||||
/* reach - mark all non-terminals in tree t as reachable */
|
va_end(ap);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emitregisterattrs(void)
|
static void emitregisterattrs(void)
|
||||||
|
@ -578,8 +580,10 @@ static void emitregisterattrs(void)
|
||||||
assert(rc->number == i);
|
assert(rc->number == i);
|
||||||
|
|
||||||
print("%1\"%s\",\n", rc->name);
|
print("%1\"%s\",\n", rc->name);
|
||||||
|
printh("#define %P%s_ATTR (1U<<%d)\n", rc->name, rc->number);
|
||||||
}
|
}
|
||||||
print("};\n\n");
|
print("};\n\n");
|
||||||
|
printh("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emitregisters(void)
|
static void emitregisters(void)
|
||||||
|
@ -713,9 +717,12 @@ static void emitdefs(Nonterm nts, int ntnumber)
|
||||||
{
|
{
|
||||||
Nonterm p;
|
Nonterm p;
|
||||||
|
|
||||||
|
printh("enum {\n");
|
||||||
for (p = nts; p; p = p->link)
|
for (p = nts; p; p = p->link)
|
||||||
print("#define %P%S_NT %d\n", p, p->number);
|
printh("%1%P%S_NT = %d,\n", p, p->number);
|
||||||
print("#define %Pmax_nt %d\n\n", ntnumber);
|
printh("%1%Pmax_nt = %d\n", ntnumber);
|
||||||
|
printh("};\n\n");
|
||||||
|
|
||||||
print("const char *%Pntname[] = {\n%10,\n");
|
print("const char *%Pntname[] = {\n%10,\n");
|
||||||
for (p = nts; p; p = p->link)
|
for (p = nts; p; p = p->link)
|
||||||
print("%1\"%S\",\n", p);
|
print("%1\"%S\",\n", p);
|
||||||
|
@ -744,6 +751,9 @@ static void emitheader(void)
|
||||||
print("#include \"mcgg_generated_header.h\"\n");
|
print("#include \"mcgg_generated_header.h\"\n");
|
||||||
if (Tflag)
|
if (Tflag)
|
||||||
print("static NODEPTR_TYPE %Pnp;\n\n");
|
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 */
|
/* computekids - compute paths to kids in tree t */
|
||||||
|
@ -1343,11 +1353,6 @@ static void emitterms(Term terms)
|
||||||
Term p;
|
Term p;
|
||||||
int k;
|
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");
|
print("static const char %Parity[] = {\n");
|
||||||
for (k = 0, p = terms; p; p = p->link)
|
for (k = 0, p = terms; p; p = p->link)
|
||||||
{
|
{
|
||||||
|
|
|
@ -143,6 +143,7 @@ void yywarn(char* fmt, ...);
|
||||||
extern int errcnt;
|
extern int errcnt;
|
||||||
extern FILE* infp;
|
extern FILE* infp;
|
||||||
extern FILE* outfp;
|
extern FILE* outfp;
|
||||||
|
extern FILE* hdrfp;
|
||||||
|
|
||||||
/* Stupid flex imports --- why mo header file? */
|
/* Stupid flex imports --- why mo header file? */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue