Get a lot of statements being generated.

This commit is contained in:
Bill Currie 2011-01-20 23:26:13 +09:00
parent e45ea4b2ae
commit 3f2793ef72

View file

@ -202,8 +202,13 @@ convert_op (int op)
return 0; return 0;
} }
} }
typedef sblock_t *(*statement_f) (sblock_t *, expr_t *);
typedef sblock_t *(*expr_f) (sblock_t *, expr_t *, operand_t **);
static sblock_t *statement_subexpr (sblock_t *sblock, expr_t *e, static sblock_t *statement_subexpr (sblock_t *sblock, expr_t *e,
operand_t **op); operand_t **op);
static sblock_t *statement_slist (sblock_t *sblock, expr_t *e);
static sblock_t * static sblock_t *
statement_call (sblock_t *sblock, expr_t *call) statement_call (sblock_t *sblock, expr_t *call)
@ -232,11 +237,18 @@ static sblock_t *
statement_branch (sblock_t *sblock, expr_t *e) statement_branch (sblock_t *sblock, expr_t *e)
{ {
statement_t *s = 0; statement_t *s = 0;
const char *opcode;
if (e->type == ex_uexpr && e->e.expr.op == 'g') { if (e->type == ex_uexpr && e->e.expr.op == 'g') {
s = new_statement ("<GOTO>"); s = new_statement ("<GOTO>");
s->opa = new_operand (op_label); s->opa = new_operand (op_label);
s->opa->o.label = &e->e.expr.e1->e.label; s->opa->o.label = &e->e.expr.e1->e.label;
} else {
opcode = convert_op (e->e.expr.op);
s = new_statement (opcode);
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
s->opb = new_operand (op_label);
s->opb->o.label = &e->e.expr.e2->e.label;
} }
sblock_add_statement (sblock, s); sblock_add_statement (sblock, s);
@ -245,160 +257,365 @@ statement_branch (sblock_t *sblock, expr_t *e)
} }
static sblock_t * static sblock_t *
statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) statement_assign (sblock_t *sblock, expr_t *e)
{ {
statement_t *s; statement_t *s;
const char *opcode; operand_t *dst;
operand_t *src;
const char *opcode = convert_op (e->e.expr.op);
if (!e) { if (e->e.expr.op == '=') {
*op = 0; sblock = statement_subexpr (sblock, e->e.expr.e1, &dst);
return sblock; sblock = statement_subexpr (sblock, e->e.expr.e2, &src);
s = new_statement (opcode);
s->opa = src;
s->opb = dst;
sblock_add_statement (sblock, s);
} else {
} }
return sblock;
}
switch (e->type) { static sblock_t *
case ex_error: expr_expr (sblock_t *sblock, expr_t *e, operand_t **op)
case ex_state: {
case ex_bool: const char *opcode;
case ex_label: statement_t *s;
case ex_block:
case ex_nil: switch (e->e.expr.op) {
internal_error (e, 0); case 'c':
case ex_expr: sblock = statement_call (sblock, e);
switch (e->e.expr.op) {
case 'c':
sblock = statement_call (sblock, e);
break;
default:
opcode = convert_op (e->e.expr.op);
if (!opcode)
internal_error (e, "ice ice baby");
s = new_statement (opcode);
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb);
*op = s->opc = new_operand (op_temp);
sblock_add_statement (sblock, s);
break;
}
break; break;
case ex_uexpr: default:
break; opcode = convert_op (e->e.expr.op);
case ex_symbol: if (!opcode)
*op = new_operand (op_symbol); internal_error (e, "ice ice baby");
(*op)->o.symbol = e->e.symbol; s = new_statement (opcode);
break; sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
case ex_temp: sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb);
*op = new_operand (op_temp); *op = s->opc = new_operand (op_temp);
break; sblock_add_statement (sblock, s);
case ex_value:
*op = new_operand (op_value);
(*op)->o.value = &e->e.value;
break; break;
} }
return sblock; return sblock;
} }
static sblock_t * static sblock_t *
statement_expr (sblock_t *sblock, expr_t *e) expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op)
{ {
sblock_t *start = sblock; return sblock;
statement_t *s; }
expr_t *se;
const char *opcode;
for (/**/; e && e->type == ex_label; e = e->next) static sblock_t *
e->e.label.dest = sblock; expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op)
for (/**/; e; e = e->next) { {
switch (e->type) { *op = new_operand (op_symbol);
case ex_error: (*op)->o.symbol = e->e.symbol;
break; return sblock;
case ex_state: }
s = new_statement ("<STATE>");
sblock = statement_subexpr (sblock, e->e.state.frame, &s->opa); static sblock_t *
sblock = statement_subexpr (sblock, e->e.state.think, &s->opb); expr_temp (sblock_t *sblock, expr_t *e, operand_t **op)
sblock = statement_subexpr (sblock, e->e.state.step, &s->opc); {
sblock_add_statement (sblock, s); *op = new_operand (op_temp);
break; return sblock;
case ex_bool: }
break;
case ex_label: static sblock_t *
sblock->next = new_sblock (); expr_value (sblock_t *sblock, expr_t *e, operand_t **op)
sblock = sblock->next; {
e->e.label.dest = sblock; *op = new_operand (op_value);
for (/**/; e->next && e->next->type == ex_label; e = e->next) (*op)->o.value = &e->e.value;
e->e.label.dest = sblock; return sblock;
break; }
case ex_block:
sblock->next = new_sblock (); static sblock_t *
sblock = sblock->next; statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op)
for (se = e->e.block.head; se; se = se->next) {
sblock = statement_expr (sblock, se); static expr_f sfuncs[] = {
break; 0, // ex_error
case ex_expr: 0, // ex_state
switch (e->e.expr.op) { 0, // ex_bool
case 'c': 0, // ex_label
sblock = statement_call (sblock, e); 0, // ex_block
break; expr_expr,
case 'i': expr_uexpr,
case 'n': expr_symbol,
case IFBE: expr_temp,
case IFB: 0, // ex_nil
case IFAE: expr_value,
case IFA: };
opcode = convert_op (e->e.expr.op); if (!e) {
s = new_statement (opcode); *op = 0;
sblock = statement_subexpr (sblock, e->e.expr.e1, return sblock;
&s->opa); }
s->opb = new_operand (op_label);
s->opb->o.label = &e->e.label; if (e->type < 0 || e->type > ex_value)
sblock_add_statement (sblock, s); internal_error (e, "bad expression type");
sblock->next = new_sblock (); if (!sfuncs[e->type])
sblock = sblock->next; internal_error (e, "unexpected expression type");
break;
default: sblock = sfuncs[e->type] (sblock, e, op);
if (e->e.expr.op < 256) return sblock;
notice (e, "e e %c", e->e.expr.op); }
else
notice (e, "e e %d", e->e.expr.op); static sblock_t *
goto non_executable; statement_ignore (sblock_t *sblock, expr_t *e)
{
return sblock;
}
static sblock_t *
statement_state (sblock_t *sblock, expr_t *e)
{
statement_t *s;
s = new_statement ("<STATE>");
sblock = statement_subexpr (sblock, e->e.state.frame, &s->opa);
sblock = statement_subexpr (sblock, e->e.state.think, &s->opb);
sblock = statement_subexpr (sblock, e->e.state.step, &s->opc);
sblock_add_statement (sblock, s);
return sblock;
}
static void
build_bool_block (expr_t *block, expr_t *e)
{
switch (e->type) {
case ex_bool:
build_bool_block (block, e->e.bool.e);
return;
case ex_label:
e->next = 0;
append_expr (block, e);
return;
case ex_expr:
if (e->e.expr.op == OR || e->e.expr.op == AND) {
build_bool_block (block, e->e.expr.e1);
build_bool_block (block, e->e.expr.e2);
} else if (e->e.expr.op == 'i') {
e->next = 0;
append_expr (block, e);
} else if (e->e.expr.op == 'n') {
e->next = 0;
append_expr (block, e);
}
return;
case ex_uexpr:
if (e->e.expr.op == 'g') {
e->next = 0;
append_expr (block, e);
return;
}
break;
case ex_block:
if (!e->e.block.result) {
expr_t *t;
for (e = e->e.block.head; e; e = t) {
t = e->next;
build_bool_block (block, e);
} }
break; return;
case ex_uexpr: }
switch (e->e.expr.op) { break;
case 'r': default:
notice (e, "RETURN"); ;
opcode = "<RETURN>"; }
if (!e->e.expr.e1 && !options.traditional) internal_error (e, "bad boolean");
opcode = "<RETURN_V>"; }
s = new_statement (opcode);
sblock = statement_subexpr (sblock, e->e.expr.e1, static int
&s->opa); is_goto (expr_t *e)
sblock_add_statement (sblock, s); {
sblock->next = new_sblock (); return e && e->type == ex_uexpr && e->e.expr.op == 'g';
sblock = sblock->next; }
case 'g':
sblock = statement_branch (sblock, e); static int
break; is_if (expr_t *e)
default: {
notice (e, "e ue %d", e->e.expr.op); return e && e->type == ex_expr && e->e.expr.op == 'i';
goto non_executable; }
static int
is_ifnot (expr_t *e)
{
return e && e->type == ex_expr && e->e.expr.op == 'n';
}
static sblock_t *
statement_bool (sblock_t *sblock, expr_t *e)
{
expr_t **s;
expr_t *l;
expr_t *block = new_block_expr ();
build_bool_block (block, e);
s = &block->e.block.head;
while (*s) {
if (is_if (*s) && is_goto ((*s)->next)) {
l = (*s)->e.expr.e2;
for (e = (*s)->next->next; e && e->type == ex_label; e = e->next) {
if (e == l) {
e = *s;
e->e.expr.op = 'n';
e->e.expr.e2 = e->next->e.expr.e1;
e->next = e->next->next;
break;
} }
break; }
case ex_symbol: s = &(*s)->next;
case ex_temp: } else if (is_ifnot (*s) && is_goto ((*s)->next)) {
case ex_nil: l = (*s)->e.expr.e2;
case ex_value: for (e = (*s)->next->next; e && e->type == ex_label; e = e->next) {
notice (e, "e %d", e->type); if (e == l) {
non_executable: e = *s;
warning (e, "Non-executable statement;" e->e.expr.op = 'i';
" executing programmer instead."); e->e.expr.e2 = e->next->e.expr.e1;
break; e->next = e->next->next;
break;
}
}
s = &(*s)->next;
} else if (is_goto (*s)) {
l = (*s)->e.expr.e1;
for (e = (*s)->next; e && e->type == ex_label; e = e->next) {
if (e == l) {
*s = (*s)->next;
l = 0;
break;
}
}
if (l)
s = &(*s)->next;
} else {
s = &(*s)->next;
} }
} }
return start; sblock = statement_slist (sblock, block->e.block.head);
return sblock;
}
static sblock_t *
statement_label (sblock_t *sblock, expr_t *e)
{
if (sblock->statements) {
sblock->next = new_sblock ();
sblock = sblock->next;
}
e->e.label.dest = sblock;
return sblock;
}
static sblock_t *
statement_block (sblock_t *sblock, expr_t *e)
{
if (sblock->statements) {
sblock->next = new_sblock ();
sblock = sblock->next;
}
sblock = statement_slist (sblock, e->e.block.head);
return sblock;
}
static sblock_t *
statement_expr (sblock_t *sblock, expr_t *e)
{
switch (e->e.expr.op) {
case 'c':
sblock = statement_call (sblock, e);
break;
case 'i':
case 'n':
case IFBE:
case IFB:
case IFAE:
case IFA:
sblock = statement_branch (sblock, e);
break;
case '=':
case PAS:
sblock = statement_assign (sblock, e);
break;
default:
if (e->e.expr.op < 256)
notice (e, "e %c", e->e.expr.op);
else
notice (e, "e %d", e->e.expr.op);
if (options.warnings.executable)
warning (e, "Non-executable statement;"
" executing programmer instead.");
}
return sblock;
}
static sblock_t *
statement_uexpr (sblock_t *sblock, expr_t *e)
{
const char *opcode;
statement_t *s;
switch (e->e.expr.op) {
case 'r':
notice (e, "RETURN");
opcode = "<RETURN>";
if (!e->e.expr.e1 && !options.traditional)
opcode = "<RETURN_V>";
s = new_statement (opcode);
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
sblock_add_statement (sblock, s);
sblock->next = new_sblock ();
sblock = sblock->next;
case 'g':
sblock = statement_branch (sblock, e);
break;
default:
notice (e, "e ue %d", e->e.expr.op);
if (options.warnings.executable)
warning (e, "Non-executable statement;"
" executing programmer instead.");
}
return sblock;
}
static sblock_t *
statement_nonexec (sblock_t *sblock, expr_t *e)
{
if (options.warnings.executable)
warning (e, "Non-executable statement; executing programmer instead.");
return sblock;
}
static sblock_t *
statement_slist (sblock_t *sblock, expr_t *e)
{
static statement_f sfuncs[] = {
statement_ignore, // ex_error
statement_state,
statement_bool,
statement_label,
statement_block,
statement_expr,
statement_uexpr,
statement_nonexec, // ex_symbol
statement_nonexec, // ex_temp
statement_nonexec, // ex_nil
statement_nonexec, // ex_value
};
for (/**/; e; e = e->next) {
if (e->type < 0 || e->type > ex_value)
internal_error (e, "bad expression type");
sblock = sfuncs[e->type] (sblock, e);
}
return sblock;
} }
sblock_t * sblock_t *
make_statements (expr_t *e) make_statements (expr_t *e)
{ {
return statement_expr (new_sblock (), e); sblock_t *sblock = new_sblock ();
// print_expr (e);
statement_slist (sblock, e);
return sblock;
} }