p->block = block;
}
+void bb_print(char k, struct basicblock* block)
+{
+}
+
/* vim: set sw=4 ts=4 expandtab : */
"modules/src/em_code+lib_k",
"modules/src/em_data+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",
"./*.h",
"util/mcgg+mcgg",
--- /dev/null
+#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 : */
+
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;
return ir;
}
-struct ir* new_regir(int reg)
+struct ir* new_wordir(arith value)
{
- struct ir* ir = new_ir0(IR_REG, EM_pointersize);
- ir->u.rvalue = reg;
- return ir;
+ return new_constir(EM_wordsize, value);
}
struct ir* new_bbir(struct basicblock* bb)
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)
- ir_print(ir->left);
- if (ir->right)
- ir_print(ir->right);
-
- printf("\t; %c ",
- ir->is_sequence ? 'S' : ' ');
- printf("$%d = ", ir->id);
- printf("%s%d(",
- ir_names[ir->opcode],
- ir->size);
+ if (ir->left && !ir->left->is_sequence)
+ ir_print(k, ir->left);
+ if (ir->right && !ir->right->is_sequence)
+ ir_print(k, ir->right);
+
+ tracef(k, "%c: %c ", k, ir->is_sequence ? 'S' : ' ');
+ tracef(k, "$%d = ", ir->id);
+ tracef(k, "%s", ir_names[ir->opcode]);
+ if (ir->size)
+ tracef(k, "%d", ir->size);
+ tracef(k, "(");
switch (ir->opcode)
{
- case IR_ICONST:
- printf("%d", ir->u.ivalue);
+ case IR_CONST:
+ case IR_LOCAL:
+ tracef(k, "%d", ir->u.ivalue);
break;
case IR_LABEL:
- printf("%s", ir->u.lvalue);
- break;
-
- case IR_REG:
- printf("%d", ir->u.rvalue);
+ tracef(k, "%s", ir->u.lvalue);
break;
case IR_BLOCK:
- printf("%s", ir->u.bvalue->name);
+ tracef(k, "%s", ir->u.bvalue->name);
break;
default:
if (ir->left)
- printf("$%d", ir->left->id);
+ tracef(k, "$%d", ir->left->id);
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 : */
# Simple terminals
-ICONST
+CONST
REG
LABEL
BLOCK
PAIR
ANY
-PHI
+LOCAL
# Magic stack operations
PUSH
DIV
MOD
NEG
-NOT
+
+ADDF
+SUBF
+MULF
+DIVF
+NEGF
AND
OR
EOR
+NOT
# Conversions
CII1
RET
# Special
-SETREG
-GETREG
+STACKADJUST
+GETRET
+SETRET
#ifndef IR_H
#define IR_H
-#include "ircodes.h"
-
enum
{
IRR_LB = -1,
IRR_RR = -4,
};
+enum
+{
+ IRS_1,
+ IRS_2,
+ IRS_4,
+ IRS_8
+};
+
struct ir
{
int id;
int rvalue;
const char* lvalue;
struct basicblock* bvalue;
- struct {
- ARRAY(struct ir, srcs);
- } phivalue;
} u;
bool is_sequence : 1;
};
struct ir* c1, struct ir* c2);
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_constir(int size, arith value);
extern struct ir* new_bbir(struct basicblock* bb);
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
header=$2
source=$3
-echo "enum {" > $header
-sed -n 's/^[A-Z].*$/IR_&,/p' < $in >> $header
-echo "};" >> $header
+awk -f - $in >$header << "EOF"
+ BEGIN {
+ print "enum {"
+ }
-echo "const char* ir_names[] = {" > $source
-sed -n 's/^[A-Z].*$/"&",/p' < $in >> $source
-echo "};" >> $source
+ /^[^#]+/ {
+ print "\tIR_" $1 ","
+ }
+
+ 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
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[])
{
symbol_init();
{
const char* name;
ARRAY(struct insn, insns);
+ ARRAY(struct ir, allirs);
ARRAY(struct ir, irs);
ARRAY(struct basicblock, inblocks);
ARRAY(struct basicblock, outblocks);
- ARRAY(struct ir, outs);
- ARRAY(struct ir, ins);
bool is_root : 1;
bool is_terminated : 1;
};
extern void fatal(const char* s, ...);
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 bb_init(void);
extern struct basicblock* bb_get(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_fileend(void);
extern void tb_procedure(struct procedure* proc);
extern void tb_regvar(arith offset, int size, int type, int priority);
+extern void compile(struct procedure* proc);
+
#endif
/* vim: set sw=4 ts=4 expandtab : */
case ps_end: /* procedure end */
tb_procedure(current_proc);
+ compile(current_proc);
current_proc = NULL;
code_bb = NULL;
static int stackptr;
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 void reset_stack(void)
if (size < EM_wordsize)
size = EM_wordsize;
return
- new_ir0(
- IR_POP, size
+ appendir(
+ new_ir0(
+ IR_POP, size
+ )
);
}
else
{
int i;
- printf("\t; stack:");
+ tracef('E', "E: stack:");
for (i=0; i<stackptr; 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)
assert(current_bb != NULL);
ir->is_sequence = true;
APPEND(current_bb->irs, ir);
+ appendallirs(ir);
- ir_print(ir);
+ ir_print('0', ir);
return ir;
}
/* 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)
{
if (offset != 0)
return
new_ir2(
- opcode, size,
+ opcode, EM_wordsize,
left, right
);
}
struct ir* srcsize = pop(EM_wordsize);
struct ir* value;
- assert(srcsize->opcode == IR_ICONST);
- assert(destsize->opcode == IR_ICONST);
+ assert(srcsize->opcode == IR_CONST);
+ assert(destsize->opcode == IR_CONST);
value = pop(srcsize->u.ivalue);
push(
new_ir2(
IR_CJUMP, 0,
new_ir2(
- irop, size,
+ irop, size,
left, right
),
new_ir2(
case op_xor: simple_alu2(opcode, value, IR_EOR); 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:
push(
new_ir1(
IR_LOAD, EM_wordsize,
- address_of_local(value)
+ new_localir(value)
)
);
break;
appendir(
new_ir2(
IR_STORE, EM_wordsize,
- address_of_local(value),
+ new_localir(value),
pop(EM_wordsize)
)
);
case op_lal:
push(
- address_of_local(value)
+ new_localir(value)
);
break;
break;
default:
- appendir(
- new_ir2(
- IR_SETREG, EM_pointersize,
- new_regir(IRR_SP),
- new_ir2(
- IR_ADD, EM_pointersize,
- new_regir(IRR_SP),
+ while ((value > 0) && (stackptr > 0))
+ {
+ struct ir* ir = pop(stack[stackptr-1]->size);
+ value -= ir->size;
+ }
+
+ if (value != 0)
+ {
+ appendir(
+ new_ir1(
+ IR_STACKADJUST, EM_pointersize,
new_wordir(value)
)
- )
- );
+ );
+ }
break;
}
break;
if (value > 0)
{
struct ir* retval = pop(value);
+ materialise_stack();
appendir(
- new_ir2(
- IR_SETREG, value,
- new_regir(IRR_RR),
+ new_ir1(
+ IR_SETRET, value,
retval
)
);
{
push(
appendir(
- new_ir1(
- IR_GETREG, value,
- new_regir(IRR_RR)
+ new_ir0(
+ IR_GETRET, value
)
)
);
{
int i;
- printf("; 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);
- }
+ tracef('0', "0: block %s\n", bb->name);
current_bb = bb;
reset_stack();
for (i=0; i<bb->insns_count; 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)
{
case PARAM_NONE:
- printf("\n");
+ tracef('E', "\n");
insn_simple(insn->opcode);
break;
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);
break;
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_lvalue(insn->opcode, insn->u.lvalue.label, insn->u.lvalue.offset);
break;
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)
- printf(" false=%s", insn->u.bvalue.right->name);
- printf("\n");
+ tracef('E', " false=%s", insn->u.bvalue.right->name);
+ tracef('E', "\n");
insn_bvalue(insn->opcode, insn->u.bvalue.left, insn->u.bvalue.right);
break;
assert(0);
}
- print_stack();
+ if (tracing('E'))
+ print_stack();
}
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)