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
3 changed files with 97 additions and 32 deletions
|
@ -24,16 +24,20 @@ MOD
|
||||||
NEG
|
NEG
|
||||||
NOT
|
NOT
|
||||||
|
|
||||||
# Conversions
|
AND
|
||||||
FROMI1
|
OR
|
||||||
FROMI2
|
EOR
|
||||||
FROMI4
|
|
||||||
FROMI8
|
|
||||||
|
|
||||||
FROMU1
|
# Conversions
|
||||||
FROMU2
|
CII1
|
||||||
FROMU4
|
CII2
|
||||||
FROMU8
|
CII4
|
||||||
|
CII8
|
||||||
|
|
||||||
|
CIU1
|
||||||
|
CIU2
|
||||||
|
CIU4
|
||||||
|
CIU8
|
||||||
|
|
||||||
# Tristate comparisons
|
# Tristate comparisons
|
||||||
COMPARES
|
COMPARES
|
||||||
|
|
|
@ -4,6 +4,8 @@ static struct e_instr insn;
|
||||||
static struct procedure* current_proc;
|
static struct procedure* current_proc;
|
||||||
static struct basicblock* current_bb;
|
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)
|
static const char* type_to_str(int type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -57,6 +59,12 @@ static const char* dlabel_to_str(label l)
|
||||||
return aprintf("__D%d", 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)
|
static struct insn* new_insn(int opcode)
|
||||||
{
|
{
|
||||||
struct insn* insn = calloc(sizeof(struct insn), 1);
|
struct insn* insn = calloc(sizeof(struct insn), 1);
|
||||||
|
@ -72,20 +80,39 @@ static void queue_insn_simple(int opcode)
|
||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case op_ret:
|
case op_bra:
|
||||||
current_bb->is_terminated = true;
|
terminate_block();
|
||||||
current_bb = NULL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void queue_insn_value(int opcode, arith value)
|
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);
|
struct insn* insn = new_insn(opcode);
|
||||||
insn->paramtype = PARAM_IVALUE;
|
insn->paramtype = PARAM_IVALUE;
|
||||||
insn->u.ivalue = value;
|
insn->u.ivalue = value;
|
||||||
APPEND(current_bb->insns, insn);
|
APPEND(current_bb->insns, insn);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void queue_insn_label(int opcode, const char* label, arith offset)
|
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->outblocks, right);
|
||||||
APPENDU(current_bb->inblocks, current_bb);
|
APPENDU(current_bb->inblocks, current_bb);
|
||||||
|
|
||||||
current_bb->is_terminated = true;
|
terminate_block();
|
||||||
current_bb = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void queue_insn_ilabel(int opcode, int label)
|
static void queue_insn_ilabel(int opcode, int label)
|
||||||
|
|
|
@ -23,7 +23,7 @@ static void push(struct ir* ir)
|
||||||
* first. */
|
* first. */
|
||||||
|
|
||||||
if (ir->size < EM_wordsize)
|
if (ir->size < EM_wordsize)
|
||||||
ir = convert(ir, EM_wordsize, IR_FROMU1);
|
ir = convert(ir, EM_wordsize, IR_CIU1);
|
||||||
|
|
||||||
stack[stackptr++] = ir;
|
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 we try to pop something which is smaller than a word, convert it first. */
|
||||||
|
|
||||||
if (size < EM_wordsize)
|
if (size < EM_wordsize)
|
||||||
ir = convert(ir, size, IR_FROMU1);
|
ir = convert(ir, size, IR_CIU1);
|
||||||
|
|
||||||
if (ir->size != size)
|
if (ir->size != size)
|
||||||
fatal("expected an item on stack of size %d, but got %d\n", size, ir->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)
|
static void simple_convert(opcode)
|
||||||
{
|
|
||||||
switch (opcode)
|
|
||||||
{
|
|
||||||
case op_cii:
|
|
||||||
{
|
{
|
||||||
struct ir* destsize = pop(EM_wordsize);
|
struct ir* destsize = pop(EM_wordsize);
|
||||||
struct ir* srcsize = pop(EM_wordsize);
|
struct ir* srcsize = pop(EM_wordsize);
|
||||||
|
@ -168,17 +164,51 @@ static void insn_simple(int opcode)
|
||||||
|
|
||||||
value = pop(srcsize->u.ivalue);
|
value = pop(srcsize->u.ivalue);
|
||||||
push(
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case op_cii: simple_convert(IR_CII1); break;
|
||||||
|
case op_ciu: simple_convert(IR_CIU1); break;
|
||||||
|
|
||||||
case op_cmp:
|
case op_cmp:
|
||||||
push(
|
push(
|
||||||
tristate_compare(EM_pointersize, IR_COMPAREU)
|
tristate_compare(EM_pointersize, IR_COMPAREU)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case op_cai:
|
||||||
|
{
|
||||||
|
struct ir* dest = pop(EM_pointersize);
|
||||||
|
|
||||||
|
materialise_stack();
|
||||||
|
appendir(
|
||||||
|
new_ir1(
|
||||||
|
IR_CALL, 0,
|
||||||
|
dest
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fatal("treebuilder: unknown simple instruction '%s'",
|
fatal("treebuilder: unknown simple instruction '%s'",
|
||||||
em_mnem[opcode - sp_fmnem]);
|
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_rmi: simple_alu2(opcode, value, IR_MOD); break;
|
||||||
case op_ngi: simple_alu1(opcode, value, IR_NEG); 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:
|
case op_lol:
|
||||||
push(
|
push(
|
||||||
new_ir1(
|
new_ir1(
|
||||||
|
@ -359,7 +394,7 @@ static void insn_ivalue(int opcode, arith value)
|
||||||
struct ir* ptr = pop(EM_pointersize);
|
struct ir* ptr = pop(EM_pointersize);
|
||||||
|
|
||||||
if (value != EM_pointersize)
|
if (value != EM_pointersize)
|
||||||
off = convert(off, EM_pointersize, IR_FROMI1);
|
off = convert(off, EM_pointersize, IR_CII1);
|
||||||
|
|
||||||
push(
|
push(
|
||||||
new_ir2(
|
new_ir2(
|
||||||
|
@ -396,7 +431,7 @@ static void insn_ivalue(int opcode, arith value)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (value != EM_pointersize)
|
if (value != EM_pointersize)
|
||||||
delta = convert(delta, value, IR_FROMI1);
|
delta = convert(delta, value, IR_CII1);
|
||||||
|
|
||||||
push(delta);
|
push(delta);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue