Treebuilder now gets to the bottom of my test file, merrily generating

(probably horribly broken) IR.
This commit is contained in:
David Given 2016-09-19 23:30:41 +02:00
parent 6ce2495aeb
commit dcba03646b
3 changed files with 97 additions and 32 deletions

View file

@ -24,16 +24,20 @@ MOD
NEG
NOT
# Conversions
FROMI1
FROMI2
FROMI4
FROMI8
AND
OR
EOR
FROMU1
FROMU2
FROMU4
FROMU8
# Conversions
CII1
CII2
CII4
CII8
CIU1
CIU2
CIU4
CIU8
# Tristate comparisons
COMPARES

View file

@ -4,6 +4,8 @@ static struct e_instr insn;
static struct procedure* current_proc;
static struct basicblock* current_bb;
static void queue_insn_label(int opcode, const char* label, arith offset);
static const char* type_to_str(int type)
{
switch (type)
@ -57,6 +59,12 @@ static const char* dlabel_to_str(label l)
return aprintf("__D%d", l);
}
static void terminate_block(void)
{
current_bb->is_terminated = true;
current_bb = NULL;
}
static struct insn* new_insn(int opcode)
{
struct insn* insn = calloc(sizeof(struct insn), 1);
@ -72,20 +80,39 @@ static void queue_insn_simple(int opcode)
switch (opcode)
{
case op_ret:
current_bb->is_terminated = true;
current_bb = NULL;
case op_bra:
terminate_block();
break;
}
}
static void queue_insn_value(int opcode, arith value)
{
switch (opcode)
{
case op_csa:
case op_csb:
{
const char* helper = aprintf(".%s%d",
(opcode == op_csa) ? "csa" : "csb",
value);
queue_insn_label(op_cal, helper, 0);
queue_insn_value(op_asp, value + EM_pointersize);
queue_insn_value(op_lfr, value);
queue_insn_simple(op_bra);
break;
}
default:
{
struct insn* insn = new_insn(opcode);
insn->paramtype = PARAM_IVALUE;
insn->u.ivalue = value;
APPEND(current_bb->insns, insn);
}
}
}
static void queue_insn_label(int opcode, const char* label, arith offset)
{
@ -109,8 +136,7 @@ static void queue_insn_block(int opcode, struct basicblock* left, struct basicbl
APPENDU(current_bb->outblocks, right);
APPENDU(current_bb->inblocks, current_bb);
current_bb->is_terminated = true;
current_bb = NULL;
terminate_block();
}
static void queue_insn_ilabel(int opcode, int label)

View file

@ -23,7 +23,7 @@ static void push(struct ir* ir)
* first. */
if (ir->size < EM_wordsize)
ir = convert(ir, EM_wordsize, IR_FROMU1);
ir = convert(ir, EM_wordsize, IR_CIU1);
stack[stackptr++] = ir;
}
@ -48,7 +48,7 @@ static struct ir* pop(int size)
/* If we try to pop something which is smaller than a word, convert it first. */
if (size < EM_wordsize)
ir = convert(ir, size, IR_FROMU1);
ir = convert(ir, size, IR_CIU1);
if (ir->size != size)
fatal("expected an item on stack of size %d, but got %d\n", size, ir->size);
@ -153,11 +153,7 @@ static struct ir* tristate_compare(int size, int opcode)
);
}
static void insn_simple(int opcode)
{
switch (opcode)
{
case op_cii:
static void simple_convert(opcode)
{
struct ir* destsize = pop(EM_wordsize);
struct ir* srcsize = pop(EM_wordsize);
@ -168,17 +164,51 @@ static void insn_simple(int opcode)
value = pop(srcsize->u.ivalue);
push(
convert(value, destsize->u.ivalue, IR_FROMI1)
convert(value, destsize->u.ivalue, opcode)
);
}
static void insn_simple(int opcode)
{
switch (opcode)
{
case op_bra:
{
struct ir* dest = pop(EM_pointersize);
materialise_stack();
appendir(
new_ir1(
IR_JUMP, 0,
dest
)
);
break;
}
case op_cii: simple_convert(IR_CII1); break;
case op_ciu: simple_convert(IR_CIU1); break;
case op_cmp:
push(
tristate_compare(EM_pointersize, IR_COMPAREU)
);
break;
case op_cai:
{
struct ir* dest = pop(EM_pointersize);
materialise_stack();
appendir(
new_ir1(
IR_CALL, 0,
dest
)
);
break;
}
default:
fatal("treebuilder: unknown simple instruction '%s'",
em_mnem[opcode - sp_fmnem]);
@ -287,6 +317,11 @@ static void insn_ivalue(int opcode, arith value)
case op_rmi: simple_alu2(opcode, value, IR_MOD); break;
case op_ngi: simple_alu1(opcode, value, IR_NEG); break;
case op_and: simple_alu2(opcode, value, IR_AND); break;
case op_ior: simple_alu2(opcode, value, IR_OR); break;
case op_xor: simple_alu2(opcode, value, IR_EOR); break;
case op_com: simple_alu1(opcode, value, IR_NOT); break;
case op_lol:
push(
new_ir1(
@ -359,7 +394,7 @@ static void insn_ivalue(int opcode, arith value)
struct ir* ptr = pop(EM_pointersize);
if (value != EM_pointersize)
off = convert(off, EM_pointersize, IR_FROMI1);
off = convert(off, EM_pointersize, IR_CII1);
push(
new_ir2(
@ -396,7 +431,7 @@ static void insn_ivalue(int opcode, arith value)
);
if (value != EM_pointersize)
delta = convert(delta, value, IR_FROMI1);
delta = convert(delta, value, IR_CII1);
push(delta);
break;