Treebuilder now gets to the bottom of my test file, merrily generating
(probably horribly broken) IR.
This commit is contained in:
parent
6ce2495aeb
commit
dcba03646b
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue