Tracing cleanup. Simplified the IR code. Some more opcodes.

This commit is contained in:
David Given 2016-09-22 00:15:48 +02:00
parent 4546dd5f22
commit 6a74cb2e11
11 changed files with 221 additions and 114 deletions

View file

@ -39,4 +39,8 @@ void bb_alias(struct basicblock* block, const char* name)
p->block = block; p->block = block;
} }
void bb_print(char k, struct basicblock* block)
{
}
/* vim: set sw=4 ts=4 expandtab : */ /* vim: set sw=4 ts=4 expandtab : */

View file

@ -24,7 +24,8 @@ cprogram {
"modules/src/em_code+lib_k", "modules/src/em_code+lib_k",
"modules/src/em_data+lib", "modules/src/em_data+lib",
"modules/src/idf+lib", "modules/src/idf+lib",
"modules/src/read_em+lib_kv", "modules/src/read_em+lib_ev",
"modules/src/string+lib",
"modules/src/system+lib", "modules/src/system+lib",
"./*.h", "./*.h",
"util/mcgg+mcgg", "util/mcgg+mcgg",

41
mach/proto/mcg/compile.c Normal file
View file

@ -0,0 +1,41 @@
#include "mcg.h"
static void print_blocks(char k, struct procedure* proc)
{
int i;
tracef(k, "%c: procedure %s\n", k, proc->name);
for (int i=0; i<proc->blocks_count; i++)
{
struct basicblock* bb = proc->blocks[i];
int j;
tracef(k, "%c: block %s\n", k, bb->name);
for (int j=0; j<bb->inblocks_count; j++)
{
struct basicblock* obb = bb->inblocks[j];
tracef(k, "%c: %s ->\n", k, obb->name);
}
for (int j=0; j<bb->irs_count; j++)
ir_print(k, bb->irs[j]);
for (int j=0; j<bb->outblocks_count; j++)
{
struct basicblock* obb = bb->outblocks[j];
tracef(k, "%c: -> %s\n", k, obb->name);
}
}
}
void compile(struct procedure* proc)
{
int i;
print_blocks('1', proc);
}
/* vim: set sw=4 ts=4 expandtab : */

View file

@ -35,18 +35,16 @@ struct ir* new_labelir(const char* label)
return ir; return ir;
} }
struct ir* new_wordir(arith value) struct ir* new_constir(int size, arith value)
{ {
struct ir* ir = new_ir0(IR_ICONST, EM_wordsize); struct ir* ir = new_ir0(IR_CONST, size);
ir->u.ivalue = value; ir->u.ivalue = value;
return ir; return ir;
} }
struct ir* new_regir(int reg) struct ir* new_wordir(arith value)
{ {
struct ir* ir = new_ir0(IR_REG, EM_pointersize); return new_constir(EM_wordsize, value);
ir->u.rvalue = reg;
return ir;
} }
struct ir* new_bbir(struct basicblock* bb) struct ir* new_bbir(struct basicblock* bb)
@ -61,51 +59,50 @@ struct ir* new_anyir(int size)
return new_ir0(IR_ANY, size); return new_ir0(IR_ANY, size);
} }
struct ir* new_phiir(int size) struct ir* new_localir(int offset)
{ {
return new_ir0(IR_PHI, size); struct ir* ir = new_ir0(IR_LOCAL, EM_pointersize);
ir->u.ivalue = offset;
return ir;
} }
void ir_print(const struct ir* ir) void ir_print(char k, const struct ir* ir)
{ {
if (ir->left) if (ir->left && !ir->left->is_sequence)
ir_print(ir->left); ir_print(k, ir->left);
if (ir->right) if (ir->right && !ir->right->is_sequence)
ir_print(ir->right); ir_print(k, ir->right);
printf("\t; %c ", tracef(k, "%c: %c ", k, ir->is_sequence ? 'S' : ' ');
ir->is_sequence ? 'S' : ' '); tracef(k, "$%d = ", ir->id);
printf("$%d = ", ir->id); tracef(k, "%s", ir_names[ir->opcode]);
printf("%s%d(", if (ir->size)
ir_names[ir->opcode], tracef(k, "%d", ir->size);
ir->size); tracef(k, "(");
switch (ir->opcode) switch (ir->opcode)
{ {
case IR_ICONST: case IR_CONST:
printf("%d", ir->u.ivalue); case IR_LOCAL:
tracef(k, "%d", ir->u.ivalue);
break; break;
case IR_LABEL: case IR_LABEL:
printf("%s", ir->u.lvalue); tracef(k, "%s", ir->u.lvalue);
break;
case IR_REG:
printf("%d", ir->u.rvalue);
break; break;
case IR_BLOCK: case IR_BLOCK:
printf("%s", ir->u.bvalue->name); tracef(k, "%s", ir->u.bvalue->name);
break; break;
default: default:
if (ir->left) if (ir->left)
printf("$%d", ir->left->id); tracef(k, "$%d", ir->left->id);
if (ir->right) if (ir->right)
printf(", $%d", ir->right->id); tracef(k, ", $%d", ir->right->id);
} }
printf(")\n"); tracef(k, ")\n");
} }
/* vim: set sw=4 ts=4 expandtab : */ /* vim: set sw=4 ts=4 expandtab : */

View file

@ -1,11 +1,11 @@
# Simple terminals # Simple terminals
ICONST CONST
REG REG
LABEL LABEL
BLOCK BLOCK
PAIR PAIR
ANY ANY
PHI LOCAL
# Magic stack operations # Magic stack operations
PUSH PUSH
@ -22,11 +22,17 @@ MUL
DIV DIV
MOD MOD
NEG NEG
NOT
ADDF
SUBF
MULF
DIVF
NEGF
AND AND
OR OR
EOR EOR
NOT
# Conversions # Conversions
CII1 CII1
@ -55,6 +61,7 @@ CJUMP
RET RET
# Special # Special
SETREG STACKADJUST
GETREG GETRET
SETRET

View file

@ -1,8 +1,6 @@
#ifndef IR_H #ifndef IR_H
#define IR_H #define IR_H
#include "ircodes.h"
enum enum
{ {
IRR_LB = -1, IRR_LB = -1,
@ -11,6 +9,14 @@ enum
IRR_RR = -4, IRR_RR = -4,
}; };
enum
{
IRS_1,
IRS_2,
IRS_4,
IRS_8
};
struct ir struct ir
{ {
int id; int id;
@ -23,9 +29,6 @@ struct ir
int rvalue; int rvalue;
const char* lvalue; const char* lvalue;
struct basicblock* bvalue; struct basicblock* bvalue;
struct {
ARRAY(struct ir, srcs);
} phivalue;
} u; } u;
bool is_sequence : 1; bool is_sequence : 1;
}; };
@ -39,13 +42,15 @@ extern struct ir* new_ir2(int opcode, int size,
struct ir* c1, struct ir* c2); struct ir* c1, struct ir* c2);
extern struct ir* new_labelir(const char* label); extern struct ir* new_labelir(const char* label);
extern struct ir* new_regir(int reg);
extern struct ir* new_wordir(arith value); extern struct ir* new_wordir(arith value);
extern struct ir* new_constir(int size, arith value);
extern struct ir* new_bbir(struct basicblock* bb); extern struct ir* new_bbir(struct basicblock* bb);
extern struct ir* new_anyir(int size); extern struct ir* new_anyir(int size);
extern struct ir* new_phiir(int size); extern struct ir* new_localir(int offset);
extern void ir_print(const struct ir* ir); extern void ir_print(char k, const struct ir* ir);
#include "ircodes.h"
#endif #endif

View file

@ -4,11 +4,33 @@ in=$1
header=$2 header=$2
source=$3 source=$3
echo "enum {" > $header awk -f - $in >$header << "EOF"
sed -n 's/^[A-Z].*$/IR_&,/p' < $in >> $header BEGIN {
echo "};" >> $header print "enum {"
}
echo "const char* ir_names[] = {" > $source /^[^#]+/ {
sed -n 's/^[A-Z].*$/"&",/p' < $in >> $source print "\tIR_" $1 ","
echo "};" >> $source }
END {
print "};"
}
EOF
awk -f - $in >$source << "EOF"
BEGIN {
print "#include \"mcg.h\""
print "#include \"ir.h\""
print "const char* ir_names[] = {"
}
/^[^#]+/ {
printf("\t\"%s\",\n", $1)
}
END {
print "};"
}
EOF

View file

@ -33,6 +33,30 @@ const char* aprintf(const char* fmt, ...)
return p; return p;
} }
bool tracing(char k)
{
switch (k)
{
case 'E': return true;
case '0': return true;
case '1': return true;
case '2': return true;
default: return true;
}
}
void tracef(char k, const char* fmt, ...)
{
va_list ap;
if (tracing(k))
{
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
}
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
symbol_init(); symbol_init();

View file

@ -77,17 +77,18 @@ struct basicblock
{ {
const char* name; const char* name;
ARRAY(struct insn, insns); ARRAY(struct insn, insns);
ARRAY(struct ir, allirs);
ARRAY(struct ir, irs); ARRAY(struct ir, irs);
ARRAY(struct basicblock, inblocks); ARRAY(struct basicblock, inblocks);
ARRAY(struct basicblock, outblocks); ARRAY(struct basicblock, outblocks);
ARRAY(struct ir, outs);
ARRAY(struct ir, ins);
bool is_root : 1; bool is_root : 1;
bool is_terminated : 1; bool is_terminated : 1;
}; };
extern void fatal(const char* s, ...); extern void fatal(const char* s, ...);
extern const char* aprintf(const char* fmt, ...); extern const char* aprintf(const char* fmt, ...);
extern void tracef(char k, const char* fmt, ...);
extern bool tracing(char k);
extern void parse_em(void); extern void parse_em(void);
@ -105,12 +106,15 @@ extern void data_bss(arith size, int init);
extern void bb_init(void); extern void bb_init(void);
extern struct basicblock* bb_get(const char* name); extern struct basicblock* bb_get(const char* name);
extern void bb_alias(struct basicblock* block, const char* name); extern void bb_alias(struct basicblock* block, const char* name);
extern void bb_print(char k, struct basicblock* block);
extern void tb_filestart(void); extern void tb_filestart(void);
extern void tb_fileend(void); extern void tb_fileend(void);
extern void tb_procedure(struct procedure* proc); extern void tb_procedure(struct procedure* proc);
extern void tb_regvar(arith offset, int size, int type, int priority); extern void tb_regvar(arith offset, int size, int type, int priority);
extern void compile(struct procedure* proc);
#endif #endif
/* vim: set sw=4 ts=4 expandtab : */ /* vim: set sw=4 ts=4 expandtab : */

View file

@ -289,6 +289,7 @@ static void parse_pseu(void)
case ps_end: /* procedure end */ case ps_end: /* procedure end */
tb_procedure(current_proc); tb_procedure(current_proc);
compile(current_proc);
current_proc = NULL; current_proc = NULL;
code_bb = NULL; code_bb = NULL;

View file

@ -6,7 +6,7 @@ static struct basicblock* current_bb;
static int stackptr; static int stackptr;
static struct ir* stack[64]; static struct ir* stack[64];
static struct ir* convert(struct ir* src, int destsize, int opcode); static struct ir* convert(struct ir* src, int destsize, int opcodebase);
static struct ir* appendir(struct ir* ir); static struct ir* appendir(struct ir* ir);
static void reset_stack(void) static void reset_stack(void)
@ -37,8 +37,10 @@ static struct ir* pop(int size)
if (size < EM_wordsize) if (size < EM_wordsize)
size = EM_wordsize; size = EM_wordsize;
return return
new_ir0( appendir(
IR_POP, size new_ir0(
IR_POP, size
)
); );
} }
else else
@ -60,13 +62,25 @@ static void print_stack(void)
{ {
int i; int i;
printf("\t; stack:"); tracef('E', "E: stack:");
for (i=0; i<stackptr; i++) for (i=0; i<stackptr; i++)
{ {
struct ir* ir = stack[i]; struct ir* ir = stack[i];
printf(" $%d.%d", ir->id, ir->size); tracef('E', " $%d.%d", ir->id, ir->size);
} }
printf(" (top)\n"); tracef('E', " (top)\n");
}
static void appendallirs(struct ir* ir)
{
if (CONTAINS(current_bb->allirs, ir))
fatal("ir reachable from more than one place");
APPEND(current_bb->allirs, ir);
if (ir->left && !ir->left->is_sequence)
appendallirs(ir->left);
if (ir->right && !ir->right->is_sequence)
appendallirs(ir->right);
} }
static struct ir* appendir(struct ir* ir) static struct ir* appendir(struct ir* ir)
@ -76,8 +90,9 @@ static struct ir* appendir(struct ir* ir)
assert(current_bb != NULL); assert(current_bb != NULL);
ir->is_sequence = true; ir->is_sequence = true;
APPEND(current_bb->irs, ir); APPEND(current_bb->irs, ir);
appendallirs(ir);
ir_print(ir); ir_print('0', ir);
return ir; return ir;
} }
@ -112,16 +127,6 @@ void tb_regvar(arith offset, int size, int type, int priority)
/* ignored */ /* ignored */
} }
static struct ir* address_of_local(int index)
{
return
new_ir2(
IR_ADD, EM_pointersize,
new_regir((index < 0) ? IRR_LB : IRR_AB),
new_wordir(index)
);
}
static struct ir* address_of_external(const char* label, arith offset) static struct ir* address_of_external(const char* label, arith offset)
{ {
if (offset != 0) if (offset != 0)
@ -162,7 +167,7 @@ static struct ir* tristate_compare(int size, int opcode)
return return
new_ir2( new_ir2(
opcode, size, opcode, EM_wordsize,
left, right left, right
); );
} }
@ -173,8 +178,8 @@ static void simple_convert(int opcode)
struct ir* srcsize = pop(EM_wordsize); struct ir* srcsize = pop(EM_wordsize);
struct ir* value; struct ir* value;
assert(srcsize->opcode == IR_ICONST); assert(srcsize->opcode == IR_CONST);
assert(destsize->opcode == IR_ICONST); assert(destsize->opcode == IR_CONST);
value = pop(srcsize->u.ivalue); value = pop(srcsize->u.ivalue);
push( push(
@ -241,7 +246,7 @@ static void simple_branch2(int opcode, int size,
new_ir2( new_ir2(
IR_CJUMP, 0, IR_CJUMP, 0,
new_ir2( new_ir2(
irop, size, irop, size,
left, right left, right
), ),
new_ir2( new_ir2(
@ -336,11 +341,17 @@ static void insn_ivalue(int opcode, arith value)
case op_xor: simple_alu2(opcode, value, IR_EOR); break; case op_xor: simple_alu2(opcode, value, IR_EOR); break;
case op_com: simple_alu1(opcode, value, IR_NOT); break; case op_com: simple_alu1(opcode, value, IR_NOT); break;
case op_adf: simple_alu2(opcode, value, IR_ADDF); break;
case op_sbf: simple_alu2(opcode, value, IR_SUBF); break;
case op_mlf: simple_alu2(opcode, value, IR_MULF); break;
case op_dvf: simple_alu2(opcode, value, IR_DIVF); break;
case op_ngf: simple_alu1(opcode, value, IR_NEGF); break;
case op_lol: case op_lol:
push( push(
new_ir1( new_ir1(
IR_LOAD, EM_wordsize, IR_LOAD, EM_wordsize,
address_of_local(value) new_localir(value)
) )
); );
break; break;
@ -349,7 +360,7 @@ static void insn_ivalue(int opcode, arith value)
appendir( appendir(
new_ir2( new_ir2(
IR_STORE, EM_wordsize, IR_STORE, EM_wordsize,
address_of_local(value), new_localir(value),
pop(EM_wordsize) pop(EM_wordsize)
) )
); );
@ -357,7 +368,7 @@ static void insn_ivalue(int opcode, arith value)
case op_lal: case op_lal:
push( push(
address_of_local(value) new_localir(value)
); );
break; break;
@ -476,17 +487,21 @@ static void insn_ivalue(int opcode, arith value)
break; break;
default: default:
appendir( while ((value > 0) && (stackptr > 0))
new_ir2( {
IR_SETREG, EM_pointersize, struct ir* ir = pop(stack[stackptr-1]->size);
new_regir(IRR_SP), value -= ir->size;
new_ir2( }
IR_ADD, EM_pointersize,
new_regir(IRR_SP), if (value != 0)
{
appendir(
new_ir1(
IR_STACKADJUST, EM_pointersize,
new_wordir(value) new_wordir(value)
) )
) );
); }
break; break;
} }
break; break;
@ -497,10 +512,10 @@ static void insn_ivalue(int opcode, arith value)
if (value > 0) if (value > 0)
{ {
struct ir* retval = pop(value); struct ir* retval = pop(value);
materialise_stack();
appendir( appendir(
new_ir2( new_ir1(
IR_SETREG, value, IR_SETRET, value,
new_regir(IRR_RR),
retval retval
) )
); );
@ -518,9 +533,8 @@ static void insn_ivalue(int opcode, arith value)
{ {
push( push(
appendir( appendir(
new_ir1( new_ir0(
IR_GETREG, value, IR_GETRET, value
new_regir(IRR_RR)
) )
) )
); );
@ -630,13 +644,7 @@ static void generate_tree(struct basicblock* bb)
{ {
int i; int i;
printf("; BLOCK %s\n", bb->name); tracef('0', "0: block %s\n", bb->name);
if (bb->inblocks_count > 0)
{
printf("; Entered from:\n");
for (i=0; i<bb->inblocks_count; i++)
printf("; %s\n", bb->inblocks[i]->name);
}
current_bb = bb; current_bb = bb;
reset_stack(); reset_stack();
@ -644,30 +652,30 @@ static void generate_tree(struct basicblock* bb)
for (i=0; i<bb->insns_count; i++) for (i=0; i<bb->insns_count; i++)
{ {
struct insn* insn = bb->insns[i]; struct insn* insn = bb->insns[i];
printf("\t; EM: %s ", em_mnem[insn->opcode - sp_fmnem]); tracef('E', "E: read %s ", em_mnem[insn->opcode - sp_fmnem]);
switch (insn->paramtype) switch (insn->paramtype)
{ {
case PARAM_NONE: case PARAM_NONE:
printf("\n"); tracef('E', "\n");
insn_simple(insn->opcode); insn_simple(insn->opcode);
break; break;
case PARAM_IVALUE: case PARAM_IVALUE:
printf("value=%d\n", insn->u.ivalue); tracef('E', "value=%d\n", insn->u.ivalue);
insn_ivalue(insn->opcode, insn->u.ivalue); insn_ivalue(insn->opcode, insn->u.ivalue);
break; break;
case PARAM_LVALUE: case PARAM_LVALUE:
printf("label=%s offset=%d\n", tracef('E', "label=%s offset=%d\n",
insn->u.lvalue.label, insn->u.lvalue.offset); insn->u.lvalue.label, insn->u.lvalue.offset);
insn_lvalue(insn->opcode, insn->u.lvalue.label, insn->u.lvalue.offset); insn_lvalue(insn->opcode, insn->u.lvalue.label, insn->u.lvalue.offset);
break; break;
case PARAM_BVALUE: case PARAM_BVALUE:
printf("true=%s", insn->u.bvalue.left->name); tracef('E', "true=%s", insn->u.bvalue.left->name);
if (insn->u.bvalue.right) if (insn->u.bvalue.right)
printf(" false=%s", insn->u.bvalue.right->name); tracef('E', " false=%s", insn->u.bvalue.right->name);
printf("\n"); tracef('E', "\n");
insn_bvalue(insn->opcode, insn->u.bvalue.left, insn->u.bvalue.right); insn_bvalue(insn->opcode, insn->u.bvalue.left, insn->u.bvalue.right);
break; break;
@ -675,18 +683,11 @@ static void generate_tree(struct basicblock* bb)
assert(0); assert(0);
} }
print_stack(); if (tracing('E'))
print_stack();
} }
assert(stackptr == 0); assert(stackptr == 0);
if (bb->outblocks_count > 0)
{
printf("; Exiting to:\n");
for (i=0; i<bb->outblocks_count; i++)
printf("; %s\n", bb->outblocks[i]->name);
}
printf("\n");
} }
void tb_procedure(struct procedure* current_proc) void tb_procedure(struct procedure* current_proc)